存在性
在前面我们提到过如果访问对象的属性返回undefined,那我们怎么来确定是对象属性值本身就是undefined,还是未定义呢?
我们常用in操作符和hasOwnProperty方法来判断。
思考如下代码:
var myObject = {
a: 1
}
console.log('a' in myObject) // true
console.log('b' in myObject) // false
console.log(myObject.hasOwnProperty('a')) // true
console.log(myObject.hasOwnProperty('b')) // false
这两种方式是有区别的:in操作符不仅会检查属性是否存在于对象本身,还会检查其整个原型链,而hasOwnProperty方法只会检查属性是否仅在对象中。
var obj1 = {
a: 1
}
var obj2 = Object.create(obj1)
obj2.b = 2
console.log('a' in obj2) // true
console.log('b' in obj2) // true
console.log(obj2.hasOwnProperty('a')) // false
console.log(obj2.hasOwnProperty('b')) // true
in操作符检查属性a、b都是true,因为对象本身和原型链中都存在,而hasOwnProperty方法检查对象obj2仅存在属性b。
我们知道,通过Object.create(null)来创建的对象是不会连接到Object.prototype的,我们来验证下两种方法的存在性:
var obj1 = Object.create(null)
obj1.a = 1
console.log('a' in obj1) // true
console.log(Object.hasOwnProperty('a')) // false
这个结果有点出乎意外,hasOwnProperty方法是仅判断对象是否存在属性,这里显式的对obj1的属性a进行了赋值,按理说是有这个属性的。
其实hasOwnProperty方法是通过对象的Object.prototype的委托来访问的,如果不存在的话,那访问就会失败,而这里通过Object.create(null)来创建对象,恰恰是没有连接Object.prototype的。
in操作符能检查对象属性是否存在,如果是数组呢?
console.log(4 in [2,4,6]) // false
这个结果看着有点不对,明明数字4在数组中是存在的。但仔细想想,in操作符检查对象本质上是检查对象的属性名是否存在,而如果把数组看做是一个对象的话,那属性名应该是其下标0,1,2。
思考如下代码:
console.log(1 in [2,4,6]) // true
in操作符检查对对象来说,是属性名是否存在,对数组来说,检查的就是下标。所以,一般是用于普通对象的检查,不用于数组。