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('qdskill');
'length' in name; // true
'qdskill' in name; // false
// Chrome输出
name => String {0: "q", 1: "d", 2: "s", 3: "k", 4: "i", 5: "l", 6: "l", length: 7, [[PrimitiveValue]]: "qdskill"}
typeof name => object
var name = 'qdskill';
'length' in name; //false
'qdskill' in name; // false
// Chrome输出
name => "qdskill"
typeof name => string

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

var obj = {
    'name': 'qdskill',
    'type': 'blog'
}
delete obj.name; // Object {type: "blog"}

name in obj; // false

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

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

obj.url = undefined;
'url' in obj; // true

hasOwnProperty()方法

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

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

先来看个简单示例:

var obj = {
    'name': 'qdskill',
    '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 = 'qdskill is website';
obj.type = 'blog';

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

!==undefined

还有一种简单的方法可以判断对象的属性是否存在,通过属性!== undefined来判断。此时会检测自身和继承来的属性。之所以使用!==而不是!=是因为!==可以区分undefinednull。但是此方法有一个弊端,当属性存在且值为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的属性

初学者学习笔记,如有不对,还希望高手指点。如有造成误解,还希望多多谅解。

原文链接:https://www.w3cplus.com/javascript/object-properties-detection-method.html

发表评论

登录后才能评论