如同 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
的奠定石。这里不作详细介绍,详细内容能够参考 - Enumerable。git
因为咱们无法改变 for in
循环自己的行为,因此咱们只能采起其余方法来过滤掉那些不但愿出如今循环内的属性,经过 《细说 Javascript 对象篇(三) : hasOwnProperty》 咱们知道 hasOwnProperty
方法是能够作到这一点的。github
仍然使用上个例子: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