访问未在对象上定义的属性和包含原始undefined 值的属性都会返回undefined。
例如:
var obj = {
a: undefined
};
obj.a; // undefined
obj.b; // undefined
区别在于a 是自己的属性,而b 不是:
obj.hasOwnProperty('a'); // true
obj.hasOwnProperty('b'); // false
在第一种情况下,a 是一个自己的属性,即使它包含 undefined 作为其值。在第二种情况下,b 不是自己的属性,访问 obj.b 将在原型链中查找名为 b 的属性。
当原型链结束时(当它到达带有null[[Prototype]] 的对象时),属性查找结束并显式返回undefined。
您应该知道hasOwnProperty 方法仅检查属性是否物理存在于对象上(拥有属性),但我们也有继承属性,为此case我们可以使用in operator,例如:
function Test () {}
Test.prototype.a = 'foo'; // instances of Test will inherit from Test.prototype
var obj = new Test(); // { a="foo", b="bar"}
obj.b = 'bar';
obj.hasOwnProperty('a'); // false
'a' in obj; // true
obj.a; // 'foo'
obj.hasOwnProperty('b'); // true
如您所见,obj 继承自 Test.prototype,a 属性不是自己的属性,但它可以通过原型链获得。这就是为什么hasOwnProperty 返回false 而in 运算符返回true。
你可以看到[[Get]]内部操作是如何解析内部属性的
注意事项:
- 访问
undefined 作为标识符在 ECMAScript 3(最广泛实施的语言标准版本)上被认为是不安全的,因为不是作为语言关键字(例如 null)只是一个全局对象的属性,并且在这个版本的规范上是可写的,这意味着如果有人替换它的值(例如window.undefined = 'LOL';),它会破坏你的代码。
@strager 提到的typeof operator 可以代替使用,例如:
if (typeof obj.prop == 'undefined') { /*....*/ }
此运算符总是返回一个字符串(使用== 是安全的:),其值取决于其操作数的类型,可能的值描述为here。
解决此问题的另一种常见方法是声明您自己的 undefined 变量,该变量在您的函数范围内可用,例如,某些库使用以下模式:
(function(undefined) {
// code here
})();
该函数有一个名为 undefined 的参数,它会立即执行而不向其传递任何值(最后一对或括号进行调用)。
也许值得一提的是,undefined global property 最终在 ECMAScript 5 中被描述为不可写(不可变,以及不可枚举和不可配置-不可删除-)。
如果你打电话:
obj.hasOwnProperty('prop');
对象上定义的方法将被执行(你不会想要这个,因为你确切知道要调用哪个方法...),因为它遮蔽来自@的方法987654365@,但是可以通过以下方式安全地调用它:
Object.prototype.hasOwnProperty.call(obj, 'prop');