细说 Javascript 对象篇(四) : for in 循环

如同 in 运算符同样,使用 for in 循环遍历对象属性时,也将往上遍历整个原型链。javascript

// Poisoning Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
    console.log(i); // prints both bar and moo
}

这里咱们要注意两点,一是 for in 循环会忽略 enumerable 设置为 false 的属性。例如一个数组的 length 属性。第二是,因为 for in 会遍历整个原型链,因此当原型链过长时,会对性能形成影响。java

enumerable 是个很陌生的词汇,实际上,你很难在 javascript 中发现它的影子,而它实际上也是做者从 ruby 中借鉴而来的。建立 enumerable 的目的不是为了独立使用,而是采用“混用”的方式,而 Prototype 中不少方法都混用了 enumerable,因此它能够说是 prototype 的奠定石。这里不作详细介绍,详细内容能够参考 - Enumerablegit

因为咱们无法改变 for in 循环自己的行为,因此咱们只能采起其余方法来过滤掉那些不但愿出如今循环内的属性,经过 《细说 Javascript 对象篇(三) : hasOwnProperty》 咱们知道 hasOwnProperty 方法是能够作到这一点的。github

使用 hasOwnProperty 过滤

仍然使用上个例子:segmentfault

// Poisoning Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
    for(var i in foo) {
        if (foo.hasOwnProperty(i)) {
            console.log(i);
        }
    }

这是惟一正确的写法,因为咱们实用了 hasOwnProperty 方法,因此此次只输出 moo。若是不适用 hasOwnProperty 方法,那么当 Object.prototype 扩展时,就会出现错误。
如今不少框架都会选择从 Object.prototype 扩展方法,因此咱们使用这些框架时,若是使用没有用 hasOwnProperty 过滤的 for in 循环时就会遇到问题。api

总结

建议养成 hasOwnProperty 过滤属性的好习惯,不要对运行环境作任何假设,也不管原生的原型对象是否被扩展。数组

参考

http://bonsaiden.github.io/JavaScript-Garden/#object.forinloopruby

相关文章
相关标签/搜索