枚举性:属性是否会出现在对象的属性枚举中。

存在性:对象中是否存在这个属性

从名字上看,首先这个对象要存在这个对象上,才能考虑是否可枚举,也就是存在性>枚举型

想一下以下代码的结果:

var myObject = {
    a:undefined
}
console.log(myObject.a); //?
console.log(myObject.b); //?

相信你已经有了答案,两个属性值都是undefined,但是会有人问,对象属性的存在性和枚举性,应该是对象属性,没道理讲属性值

myObject.amyObject.b都为undefined。区别是:a作为对象属性存在,属性值是undefined,但因为没有在对象上找到b的同名属性,甚至可能原型链上也不存在,返回了undefined。那么我们区分这两种情况呢?也就是 我们如何判断对象上是否存在某个属性

var myObject ={
 a:2   
};
console.log( 'a' in myObject);// true
console.log( 'b' in myObject);// false
console.log(myObject.hasOwnProperty('a'));//true
console.log(myObject.hasOwnProperty('b'));//false
for(var prop in myObject){
    if(prop==='a') console.log(true;)
} //true
Object.getOwnPropertyNames(myObject);//['a']
Object.keys();//['a']

in操作符 用来检测属性是否存在于对象以及其[[Prototype]]原型链中。

obj.hasOwnProperty(…)用来检测属性是否存在于对象上,不会检查其[[Prototype]]原型链

in操作符的特殊性:

  • 对于数组,检测属性名是否存在
  • 对于数组,检测数组的下标/索引

刚才我们使用了遍历如for...inObject.getOwnPropertyNamesObject.keys(),尝试列出对象上的所有属性,那么他们有什么区别呢?我们改造下以上的代码:

var myObject = {
    a:2
}
Object.defineProperty(myObject,"a",{
    enumerable:false
})
Object.defineProperty(myObject,"b",{
    enumerable:true,
    value:2
})
//----------------
for(var prop in myObject){
    console.log(prop,myObject[prop]);
} //b 2
Object.getOwnPropertyNames(myObject);//['a','b']
Object.keys(myObject);//['b']

可以看到,myObject中确确实实存在了属性a,但就是没有遍历出来。这个与当前属性的属性描述符中定义的 ennmerable有关。

在定义对象时,对象上的属性默认都是可见的,即ennmerable:true,如果想屏蔽特殊的属性,可以修改为false

Object.keys() & Object.getOwnPropertyNames(…)

相同点:都只查找对象直接含有的属性,不会去其原型链[[Prototype]]上寻找

不同点:Object.keys() 会遍历所有可枚举的属性

​ Object.getOwnPropertyNames(…) 会遍历所有的对象属性

for…in 用来遍历对象上以及其原型链上的可枚举属性。

通过以上分析,我们可以在判断对象属性时更加清晰些。


王大山
28 声望2 粉丝