你不知道的JS系列 ( 38 ) - 对象属性是否存在
myObject.a 的属性访问返回值可能是 undefined,但是这个值有可能是属性中存储的 undefined,也可能是因为属性不存在所以返回 undefined
var myObject = { a: 2 } ('a' in myObject); // true ('b' in myObject); // false myObject.hasOwnProperty('a'); // true myObject.hasOwnProperty('b'); // false
in 操作符会检查属性是否存在对象及其原型链中。hasOwnProperty(...) 只会检查属性是否在 myObect 对象中,不会检查原型链。如果要使用 hasOwnProperty(...) 检查至原型链,可以强制绑定使用
Object.prototype.hasOwnProperty.call(myObject, 'a')
枚举
var myObject = {}; Object.defineProperty(myObject, 'a', { enumerable: true, value: 2 // a 可枚举 }); Object.defineProperty(myObject, 'b', { enumerable: false, value: 3 // b 不可枚举 }); myObject.b; // 3 ('b' in myObject); // true myObject.hasOwnProperty('b'); // true for (var k in myObject) { console.log(k, myObject[k]) } // 'a' 2
myObject.b 确实存在并且有访问值,但是却不会出现在 for...in 循环中,原因是 ’可枚举‘ 就相当于 ‘可以出现在属性遍历中’
也可以通过另一种方式来区分属性是否可枚举
var myObject = {}; Object.defineProperty(myObject, 'a', { enumerable: true, value: 2 // a 可枚举 }); Object.defineProperty(myObject, 'b', { enumerable: false, value: 3 // b 不可枚举 }); myObject.propertyIsEnumerable('a'); // true myObject.propertyIsEnumerable('b'); // false Object.keys(myObject); // ['a'] Object.getOwnPropertyNames(myObject); // ['a', 'b']
propertyIsEnumerable(...) 会检查给定的属性是否直接存在于对象中(而不是在原型链上)并且满足 enumerable: true
Object.keys(...) 会返回一个数组,包含所有可枚举属性,Object.getOwnPropertyNames(...)会返回一个数组,包含所有属性,无论它们是否可枚举