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

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

in运算符
hasOwnProperty()方法
propertyIsEnumerable()方法
!==undefined
接下来看这四种方法怎么检测对象属性。

in运算符

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

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

var myCar = {
    'make': 'Honda',
    'model': 'Accord',
    'year': 1998
}

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

var name = new String('w3cplus');
'length' in name; // true
'w3cplus' in name; // false

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

var name = 'w3cplus';
'length' in name; //false
'w3cplus' in name; // false

// Chrome输出
name => "w3cplus"
typeof name => string
使用delete运算符删除了一个对象一个属性,这时使用in运算符检测删除的属性时会返回false:

var obj = {
    'name': 'w3cplus',
    'type': 'blog'
}

delete obj.name; // Object {type: "blog"}

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

var obj = {
    'name': 'w3cplus',
    'type': 'blog'
}

obj.url = undefined;

'url' in obj; // true
hasOwnProperty()方法

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

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

先来看个简单示例:

var obj = {
    'name': 'w3cplus',
    'type': 'blog'
}

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

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

var foo = {
    hasOwnProperty: function() {
        return false;
    },
    bar: 'Here be dragons'
};

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()方法在普通对象和数组上的基本用法:

var obj = {};
obj.name = 'w3cplus is website';
obj.type = 'blog';

obj.propertyIsEnumerable('name');     // true
obj.propertyIsEnumerable('type');     // true
obj.propertyIsEnumerable(0);          // false
obj.propertyIsEnumerable('toString'); // false
!==undefined

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

var obj = {
    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。如下面的代码所示:

var obj = {
    x : undefined // 属性显式赋值为undefined
}
obj.x !== undefined; //false,属性存在,但值为undefined
obj.y !== undefined; //false,属性不存在
"x" in obj; // true 属性存
"y" in obj; // false 属性不存在
delete obj.x; // 删除属性x
"x" in obj; // false 属性不存
总结

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

in 自身存在的属性,继承的属性,返回true
hasOwnProperty() 自身存在的属性返回true,继承属性返回false
propertyIsEnumerable() 自身存在的属性,且为枚举属性返回true,
!== undefined 自身存在的属性,继承的属性,不能识别值为undefined的属性

猜你喜欢

转载自jackyrong.iteye.com/blog/2341920