JavaScript学习笔记:对象属性检测

JavaScript对象可以看作是一个属性的集合,很多时候需要看某个属性是否存在于某个对象中。在JavaScript中对象属性的检测主要有以下几种方法。

in运算符

hasOwnProperty()方法

propertyIsEnumerable()方法

!==undefined

接下来看这四种方法怎么检测对象属性。

in运算符

使用in运算符可以检测对象属性,如果指定的属性存在于指定的对象中,就会返回true,反之返回的是false。

下面的例子演示了in是如何检测对象属性的。

varmyCar={

'make':'Honda',

'model':'Accord',

'year':1998

}

'make'inmyCar;//true

'name'inmyCar;//false

'toString'inmyCar;//true

在使用in运算符做对象属性检测时,运算符右侧必须是一个对象,比如可以是一个string包装的对象,但不能是一个字符串原始值。

varname=newString('w3cplus');

'length'inname;//true

'w3cplus'inname;//false

//Chrome输出

name=>String{0:"w",1:"3",2:"c",3:"p",4:"l",5:"u",6:"s",length:7,[[PrimitiveValue]]:"w3cplus"}

typeofname=>object

varname='w3cplus';

'length'inname;//false

'w3cplus'inname;//false

//Chrome输出

name=>"w3cplus"

typeofname=>string

使用delete运算符删除了一个对象一个属性,这时使用in运算符检测删除的属性时会返回false:

varobj={

'name':'w3cplus',

'type':'blog'

}

deleteobj.name;//Object{type:"blog"}

nameinobj;//false

如果你只是将一个属性的值赋值为undefined,而没有用delete删除它,这个时候使用in运算符检测对象属性时依旧会返回true。

varobj={

'name':'w3cplus',

'type':'blog'

}

obj.url=undefined;

'url'inobj;//true

hasOwnProperty()方法

使用hasOwnProperty()方法可以判断某个对象是否含有指定的自身属性。使用这个方法,所有承继继承了Object.prototype的对象都会从原型链上继承到hasOwnProperty()方法上。而且该方法会忽略掉那些从原型上继承到的属性。

如果对象obj包含指定的prop属性的话,使用hasOwnProperty()方法将返回true值,反之将会返回false。

先来看个简单示例:

varobj={

'name':'w3cplus',

'type':'blog'

}

obj.hasOwnProperty('name');//true

obj.hasOwnProperty('toString');//false

只有hasOwnProperty()可以给出正确和期望的结果,这在遍历对象的属性时会很有用。没有其它方法可以用来排除原型链上的属性,而不是定义在对象自身上的属性。

hasOwnProperty()方法只会查找自身属性,不会根据原型链进行查找。而且hasOwnProperty()方法在碰到对象拥有自已的hasOwnProperty方法时,其原型链上的同名方法hasOwnProperty()就会被遮蔽。

varfoo={

hasOwnProperty:function(){

returnfalse;

},

bar:'Herebedragons'

};

foo.hasOwnProperty('bar');//始终返回false

如果担心hasOwnProperty()方法有可能被遮蔽的这种情况,可以直接使用原型链上真正的hasOwnProperty方法:

({}).hasOwnProperty.call(foo,'bar');//true

Object.prototype.hasOwnProperty.call(foo,'bar');//true

propertyIsEnumerable()方法

propertyIsEnumerable()方法是hasOwnProperty()方法的一个升级版。在JavaScript中每个对象都有一个propertyIsEnumerable()方法。使用这个方法可以判断出指定的对象obj里的属性prop是否可枚举,也就是说该属性是否可以通过for...in循环遍历到,不过有些属性虽然可以通过for...in循环遍历到,但因为它们不是自身属性,而是从原型链上继承的属性,所以该方法也会返回false。如果对象没有指定的属性,该方法返回false。

先来看一个propertyIsEnumerable()方法在普通对象和数组上的基本用法:

varobj={};

obj.name='w3cplusiswebsite';

obj.type='blog';

obj.propertyIsEnumerable('name');//true

obj.propertyIsEnumerable('type');//true

obj.propertyIsEnumerable(0);//false

obj.propertyIsEnumerable('toString');//false

!==undefined

还有一种简单的方法可以判断对象的属性是否存在,通过属性!==undefined来判断。此时会检测自身和继承来的属性。之所以使用!==而不是!=是因为!==可以区分undefined和null。但是此方法有一个弊端,当属性存在且值为undefined时,无法做出准确判断。如:

varobj={

x:"1",

y:undefined,

z:null

};

console.log(obj.x!==undefined);//true属性存在

console.log(obj.y!==undefined);//false此时会出现歧义,不能准确判断属性是不存在还是属性值为undefined

console.log(obj.z!==undefined);//true属性存在

console.log(obj.z!=undefined);//false!=不能区分undefined和null,将两者同等对待

console.log(obj.w!==undefined);//false属性不存在

console.log(obj.toString!==undefined);//true存在toString函数属性。

然而有一种场景只能使用in运算符,而不能使用上述属性访问的方式。in可以区分不存在的属性和存在的属性但其值为undefined。如下面的代码所示:

varobj={

x:undefined//属性显式赋值为undefined

}

obj.x!==undefined;//false,属性存在,但值为undefined

obj.y!==undefined;//false,属性不存在

"x"inobj;//true属性存

"y"inobj;//false属性不存在

deleteobj.x;//删除属性x

"x"inobj;//false属性不存

总结

上面简单的整理了几种对象属性检测的方法,下面简单的做一下相关的总结:

in自身存在的属性,继承的属性,返回true

hasOwnProperty()自身存在的属性返回true,继承属性返回false

propertyIsEnumerable()自身存在的属性,且为枚举属性返回true,

!==undefined自身存在的属性,继承的属性,不能识别值为undefined的属性

相关推荐