在阅读 lodash 源码的时候遇到的一个问题 hasOwnProperty 的用法 查阅了相关的资料这里将这个疑惑点好好的梳理一下。
判断一个属性是定义在对象本身而不是继承自原型链,我们需要使用从 Object.prototype 继承而来的 hasOwnProperty 方法。
hasOwnProperty 方法是 Javascript 中唯一一个处理对象属性而不会往上遍历原型链的。
使用 hasOwnProperty 方法判断属性是否存在
看一个例子下面这个例子展示了 是否含有自身的属性prop。
o = new Object();
o.prop = 'exists';
function changeO() {
o.newprop = o.prop;
delete o.prop;
}
o.hasOwnProperty('prop'); // 返回 true
changeO();
o.hasOwnProperty('prop'); // 返回 false
下面两个例子演示了 hasOwnProperty 方法对待自身属性和继承属性的区别:
o = new Object();
o.prop = 'exists';
o.hasOwnProperty('prop'); // 返回 true
o.hasOwnProperty('toString'); // 返回 false 这个方法显然是继承自 Object对象
o.hasOwnProperty('hasOwnProperty'); // 返回 false 这个方法显然是继承自 Object对象
Object.prototype.bar = 1; // 在Object的对象的原型上面添加一个属性 bar
var foo = {goo: undefined}; // 创建一个对象foo
foo.bar; // 1
'bar' in foo; // true 单纯看一下 bar 也是在foo上面的这个属性继承源于Object
foo.hasOwnProperty('bar'); // false
foo.hasOwnProperty('goo'); // true
在这里,只有 hasOwnProperty 能给出正确答案,这在遍历一个对象的属性时是非常必要的。
Javascript 中没有其他方法能判断一个属性是定义在对象本身还是继承自原型链。
遍历一个对象的所有自身属性
下面的例子演示了如何在遍历一个对象的所有属性时忽略掉继承属性,
注意这里 for...in 循环只会遍历可枚举属性,所以不应该基于这个循环中没有不可枚举的属性而得出 hasOwnProperty 是严格限制于可枚举项目的(如同 Object.getOwnPropertyNames())。
var buz = {
fog: 'stack'
};
// 下面这个for in 循环 使用 hasOwnProperty 区分了自有属性和继承属性
for (var name in buz) {
if (buz.hasOwnProperty(name)) {
alert("this is fog (" + name + ") for sure. Value: " + buz[name]);
}
else {
alert(name); // toString or something else
}
}
使用 hasOwnProperty 作为属性名
JavaScript 并没有保护 hasOwnProperty 属性名,
因此某个对象是有可能存在使用这个属性名的属性,使用外部的 hasOwnProperty 获得正确的结果是需要的:
var foo = {
hasOwnProperty: function() {
return false;
},
bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // 始终返回 false
// 如果担心这种情况,可以直接使用原型链上真正的 hasOwnProperty 方法
({}).hasOwnProperty.call(foo, 'bar'); // true
// 也可以使用 Object 原型上的 hasOwnProperty 属性
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
网友评论