检测未定义的对象属性
技术背景
在JavaScript中,准确检测对象属性是否未定义是常见的需求。但由于undefined
的特殊性以及JavaScript语言的一些特性,使得检测未定义属性变得复杂。undefined
既可以表示变量未赋值,也可以表示对象没有该属性。此外,在不同的JavaScript版本中,undefined
的可写性也有所不同。
实现步骤
1. 检查属性值是否为undefined
1 2 3
| if(o.myProperty === undefined) { alert("myProperty value is the special value `undefined`"); }
|
2. 检查对象是否实际拥有该属性
1 2 3
| if(!o.hasOwnProperty('myProperty')) { alert("myProperty does not exist"); }
|
3. 检查标识符关联的值是否为undefined
或标识符未声明
1 2 3
| if(typeof myVariable === 'undefined') { alert('myVariable is either the special value `undefined`, or it has not been declared'); }
|
4. 避免undefined
被重定义的情况
1 2 3
| if(myVariable === void 0) { alert("myVariable is the special value `undefined`"); }
|
核心代码
获取所有未定义属性的路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| function getAllUndefined(object) { function convertPath(arr, key) { var path = ""; for (var i = 1; i < arr.length; i++) { path += arr[i] + "->"; } path += key; return path; } var stack = []; var saveUndefined = []; function getUndefiend(obj, key) { var t = typeof obj; switch (t) { case "object": if (t === null) { return false; } break; case "string": case "number": case "boolean": case "null": return false; default: return true; } stack.push(key); for (k in obj) { if (obj.hasOwnProperty(k)) { v = getUndefiend(obj[k], k); if (v) { saveUndefined.push(convertPath(stack, k)); } } } stack.pop(); } getUndefiend({ "": object }, ""); return saveUndefined; }
|
最佳实践
- 检查变量是否未定义:通常使用
typeof
来检查未声明的变量,避免引用错误。
1 2 3
| if(typeof myVar === "undefined") { }
|
- 检查对象属性是否未定义:使用
=== undefined
来检查对象属性,简单直接。
1 2 3
| if(obj.prop === undefined) { }
|
常见问题
1. undefined
被重定义
在ES5之前,全局对象的undefined
属性是可写的,可能导致foo === undefined
的检查意外失败。现代JavaScript中,undefined
是只读的,但函数内部仍可定义同名变量。可以使用void 0
来获取真正的undefined
值。
2. typeof
的使用误区
typeof
用于检查变量是否未定义时,可能会隐藏拼写错误。因为它不会抛出错误,而是返回false
。例如:
1 2 3 4
| var snapshot; if (typeof snaposhot === 'undefined') { }
|
3. 检查未声明的变量
直接使用myVar === undefined
检查未声明的变量会抛出ReferenceError
,而typeof myVar === 'undefined'
不会。但应尽量避免这种情况,因为JavaScript是静态作用域语言,应明确变量是否声明。