Javascript学习笔记之 对象篇(四) : for in 循环
先上范例:
//PoisoningObject.prototype Object.prototype.bar=1; varfoo={moo:2}; for(variinfoo){ console.log(i);//printsbothbarandmoo }
这里我们要注意两点,一是forin循环会忽略enumerable设置为false的属性。例如一个数组的length属性。第二是,由于forin会遍历整个原型链,所以当原型链过长时,会对性能造成影响。
enumerable是个很陌生的词汇,实际上,你很难在javascript中发现它的影子,而它实际上也是作者从ruby中借鉴而来的。创建enumerable的目的不是为了独立使用,而是采用“混用”的方式,而Prototype中很多方法都混用了enumerable,所以它可以说是prototype的奠基石。这里不做详细介绍,详细内容可以参考-Enumerable。
由于我们没法改变forin循环本身的行为,所以我们只能采取其他方法来过滤掉那些不希望出现在循环内的属性,通过《Javascript学习笔记之对象篇(三):hasOwnProperty》我们知道hasOwnProperty方法是可以做到这一点的。
使用hasOwnProperty过滤
仍然使用上个例子:
//PoisoningObject.prototype Object.prototype.bar=1; varfoo={moo:2}; for(variinfoo){ if(foo.hasOwnProperty(i)){ console.log(i); } }
这是唯一正确的写法,由于我们实用了hasOwnProperty方法,所以这次只输出moo。如果不适用hasOwnProperty方法,那么当Object.prototype扩展时,就会出现错误。
现在很多框架都会选择从Object.prototype扩展方法,所以我们使用这些框架时,如果使用没有用hasOwnProperty过滤的forin循环时就会遇到问题。
总结
建议养成hasOwnProperty过滤属性的好习惯,不要对运行环境做任何假设,也无论原生的原型对象是否被扩展。