[已解决]无法读取 JavaScript 中未定义的属性
[Solved] Cannot read Properties of Undefined in JavaScript
出现“无法读取未定义的属性”错误的原因有多种:
- 访问存储值的变量的属性
undefined
。 - 访问不存在的 DOM 元素的属性。
- 在声明 DOM 元素的 HTML 上方插入 JS 脚本标记。
最常见的情况是,如果您尝试访问值为 的变量的属性,则会发生错误undefined
。
const person = undefined; // ⛔️ Cannot read properties of undefined (reading 'name') person.name;
我们试图访问导致错误的值name
的属性。undefined
使用可选的链接 (?.) 运算符
使用可选的链接 (?.) 运算符
在访问变量之前检查
变量是否为空。
如果变量是undefined
or null
,运算符会短路而不是抛出错误。
const person = undefined; // ✅ Using optional chaining console.log(person?.name); // 👉️ undefined console.log(person?.name?.first); // 👉️ undefined // ✅ Using if / else if (person?.name) { console.log(person.name); } else { // 👇️ this runs console.log('person.name not found'); } // ✅ Using logical AND (&&) operator console.log(person && person.name); // 👉️ undefined
可选链 (?.) 运算符允许我们访问对象的属性,而不会在引用无效时抛出错误。
undefined
可选链接 (?.) 运算符不会抛出错误,而是在引用等于or时短路返回。 undefined
null
使用逻辑与运算符
您还可以以类似的方式使用逻辑与 (&&) 运算符。
const person = undefined; console.log(person && person.name); // 👉️ undefined // 👇️ undefined console.log(person && person.name && person.name.first);
如果左边的值是假的(例如) ,逻辑
AND (&&)
运算符不会计算右边的值。undefined
您可以使用与可选链接 (?.) 运算符类似的方式使用逻辑与 (&&) 运算符。
let person; console.log(person); // 👉️ undefined // ✅ using optional chaining if (person?.address?.country) { console.log(person.address.country); } // ✅ using logical AND (&&) if (person && person.address && person.address.country) { console.log(person.address.country); }
访问索引不存在的数组
一个常见的值来源undefined
是在不存在的索引处访问数组。
使用可选的链接 (?.) 运算符或逻辑与 (&&) 运算符以
确保数组索引
在访问属性之前存在。
const arr = []; // ⛔️ Cannot read properties of undefined (reading 'name') console.log(arr[0].name); // ❌ Bad console.log(arr[0]?.name); // ✅ Good console.log(arr[0] && arr[0].name); // ✅ Good
undefined
如果您必须访问可能不存在的索引处的嵌套数组元素,请使用相同的方法。
const arr = [['a', 'b', 'c']]; console.log(arr?.[0]); // 👉️ ['a', 'b', 'c'] console.log(arr?.[0]?.[0]); // 👉️ a console.log(arr?.[0]?.[0]?.[1]); // 👉️ undefined console.log(arr?.[0]?.[0]?.[1]?.[0]); // 👉️ undefined
您还可以使用可选的链接 (?.) 运算符来提供在变量或其属性返回时要返回的值undefined
。
let person; const name = person?.name ?? 'default'; console.log(name); // 👉️ 'default' const country = person?.address?.country ?? 'default'; console.log(country); // 👉️ 'default'
person
存储一个值,undefined
因为我们没有初始化它。如果访问变量name
的属性person
返回undefined
,则返回无效合并 (??) 运算符左侧的值。
我已经写了一篇关于如何检查 JavaScript 中是否存在数组索引的详细指南
。
为变量存储未定义值时提供回退值
解决错误的另一种方法是在变量存储虚假值(例如 )时提供回退值undefined
。
const name = undefined; const result1 = (name ?? 'bobby').toUpperCase(); console.log(result1); // 👉️ BOBBY const obj = undefined; const result2 = (obj ?? {name: 'bobby'}).name; console.log(result2); // 👉️ bobby
如果左侧的值为空值(或
),则空值合并运算符 (??)返回
右侧的值。null
undefined
在所有其他情况下,它返回左侧的值。
出现错误的另一个常见原因是访问 DOM 元素上不存在的属性。
追踪变量赋值的undefined
位置
undefined
已声明但未赋值的变量在 JavaScript 中的值为
。
let employee; console.log(employee); // 👉️ undefined // ⛔️ TypeError: Cannot read properties of undefined (reading 'name') console.log(employee.name);
我们声明了employee
变量但没有给它赋值,所以它存储了一个undefined
值。
相反,在声明变量时对其进行初始化。
let employee = {}; console.log(employee.name); // 👉️ undefined
我们将变量设置employee
为空对象,但您可以使用适合您用例的任何其他值,例如空数组[]
或空字符串
""
。
undefined
当您在不存在的索引处访问数组时,您也会得到一个值。
let employees = []; console.log(employees[1]); // 👉️ undefined // ⛔️ TypeError: Cannot read properties of undefined (reading 'push') console.log(employees[1].push('a'));
如果需要向数组添加元素,请调用push()
数组上的方法,而无需在特定索引处访问它。
let employees = []; employees.push('bobby'); employees.push('hadz'); employees.push('com'); // 👇️ [ 'bobby', 'hadz', 'com' ] console.log(employees);
如果您打算访问特定数组元素的属性,请使用可选的链接运算符。
let employees = ['a', 'b']; const result = employees[100]?.toUpperCase(); console.log(result); // 👉️ undefined
如果指定索引处的数组元素不存在,则可选链接运算符返回undefined
而不是抛出错误。
如果错误仍然存在,您必须追踪变量在何处被赋值
undefined
。
undefined
是将不返回任何内容的函数的输出分配给变量。许多在适当位置改变对象的内置方法返回undefined
。
所有不返回值的 JavaScript 函数都返回undefined
。
您可能正在访问不存在的索引处的数组或对象中不存在的属性。
确保你访问的 DOM 元素存在
要解决“无法读取未定义的属性”错误,请确保您正在访问的 DOM 元素存在。
在使用该方法后尝试访问不存在的索引处的属性时,通常会抛出该错误getElementsByClassName()
。
const boxes = document.getElementsByClassName('does-not-exist'); console.log(boxes); // [] // ⛔️ Cannot read properties of undefined (reading 'innerHTML') console.log(boxes[0].innerHTML);
相反,更正类名并使用可选的链接 (?.) 运算符来
检查索引处的 DOM 元素是否0
包含属性。
const boxes = document.getElementsByClassName('does-not-exist'); console.log(boxes); // [] // ✅ check for existence of property if (boxes[0]?.innerHTML) { console.log(boxes[0].innerHTML); } else { // 👇️ this runs console.log('element does not exist'); }
如果索引处的元素0
包含该innerHTML
属性,我们的if
块将运行,否则else
运行该块。
在body标签底部插入JS脚本标签
确保在标签底部插入 JS 脚本标签body
。
JS 脚本标签应该放在 HTML 元素声明之后。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <script src="index.js"></script> <!-- ❌ BAD - SHOULD BE ABOVE SCRIPT TAG ❌ --> <div class="box">Hello</div> </body> </html>
脚本标记在声明类名为 的元素
index.js
之前运行。div
box
如果您尝试访问脚本div
中的元素index.js
,它将不可用,从而导致错误。
const boxes = document.getElementsByClassName('box'); console.log(boxes); // 👉️ [] // ⛔️ Cannot read properties of undefined (reading 'innerHTML') console.log(boxes[0].innerHTML);
在声明 HTML 元素之后,您必须将 JS 脚本放在 body 标记的底部。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <div class="box">Hello</div> <!-- ✅ Good - Script is run after HTML is declared ✅ --> <script src="index.js"></script> </body> </html>
box
现在可以在脚本内部访问具有类名的 div 元素index.js
。
const boxes = document.getElementsByClassName('box'); console.log(boxes); console.log(boxes[0].innerHTML); // 👉️ "Hello"
HTML 代码是从上到下解析的,因此 script 标签必须放在 body 标签的底部,在它需要访问的所有 DOM 元素之后。
# 结论
当您尝试访问存储值的变量的属性或方法时,会发生“无法读取未定义的属性”错误undefined
。
undefined
要解决该错误,请在访问属性或方法之前检查变量是否存在。
# 额外资源
您可以通过查看以下教程来了解有关相关主题的更多信息: