笔记 03 JS 对象属性遍历

原文地址

1 hasOwnProperty 函数

1.1 不对hasOwnProperty做修改

继承自 Object.prototype 的 hasOwnProperty 方法:

  • 可以判断一个对象的 自定义属性 原型链上的属性
  • 唯一一个处理属性但是不查找原型链的函数。

注意: 通过判断一个属性是否 undefined 是不够的。
因为一个属性可能确实存在,只不过它的值被设置为 undefined。

// 修改Object.prototype
Object.prototype.bar = 1;
var foo = {goo: undefined};

foo.bar; // 1
'bar' in foo; // true

foo.hasOwnProperty('bar'); // false (原型链上的属性) 可以用来排除原型链上的属性
foo.hasOwnProperty('goo'); // true (自定义属性)

1.2 hasOwnProperty作为属性 (安全编码)

JavaScript 不会保护 hasOwnProperty 被非法占用,
因此如果一个对象碰巧存在这个属性,
就需要使用外部的 hasOwnProperty 函数来获取正确的结果

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

foo.hasOwnProperty('bar'); // 总是返回 false

/**
 * 一个广泛使用的类库 Prototype 就扩展了原生的 JavaScript 对象。
 * 因此,当这个类库被包含在页面中时,
 * 不使用 hasOwnProperty 过滤的 for in 循环难免会出问题。
 */

// 使用其它对象的 hasOwnProperty,并将其上下文设置为foo
({}).hasOwnProperty.call(foo, 'bar'); // true
Object.hasOwnProperty.call(foo, 'bar'); // true

2 for in 循环

和 in 操作符一样,
for in 循环同样在查找对象属性时遍历原型链上的所有属性

注意: for in 循环不会遍历那些 enumerable 设置为 false 的属性;比如数组的 length 属性。
注意: 由于 for in 总是要遍历整个原型链,因此如果一个对象的继承层次太深的话会影响性能。

// 修改 Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
    console.log(i); // 输出两个属性:bar 和 moo
}

// foo 变量是上例中的
// 过滤数据
for(var i in foo) {
    if (foo.hasOwnProperty(i)) {
        console.log(i); // 输出:moo
    }
}