细说JavaScript对象(4): for in 循环
如同 in 运算符一样,使用 for in 循环遍历对象属性时,也将往上遍历整个原型链。
// 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 会遍历整个原型链,所以当原型链过长时,会对性能造成影响。
enumerable 是个很陌生的词汇,实际上,你很难在 JavaScript 中发现它的影子,而它实际上也是作者从 ruby中借鉴而来的。创建 enumerable 的目的不是为了独立使用,而是采用“混用”的方式,而 Prototype 中很多方法都混用了 enumerable,所以它可以说是 prototype 的奠基石。这里不做详细介绍,详细内容可以参考 -Enumerable。
由于我们没法改变 for in 循环本身的行为,所以我们只能采取其他方法来过滤掉那些不希望出现在循环内的属性,通过《细说 JavaScript 对象篇(三) : hasOwnProperty》 我们知道 hasOwnProperty 方法是可以做到这一点的。
使用 hasOwnProperty 过滤
仍然使用上个例子:
// 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 循环时就会遇到问题。
总结
建议养成 hasOwnProperty 过滤属性的好习惯,不要对运行环境做任何假设,也无论原生的原型对象是否被扩展。
参考
http://segmentfault.com/blog/stephenlee/1190000000480560
http://bonsaiden.github.io/JavaScript-Garden/#object.forinloop
延伸阅读:
细说JavaScript对象(3):hasOwnProperty
细说JavaScript对象(4): for in 循环的更多相关文章
- 细说JavaScript对象(2):原型对象
JavaScript 并没有类继承模型,而是使用原型对象 prototype 进行原型式继承. 尽管人们经常将此看做是 JavaScript 的一个缺点,然而事实上,原型式继承比传统的类继承模型要更加 ...
- 细说JavaScript对象(3):hasOwnProperty
判断一个属性是定义在对象本身而不是继承自原型链,我们需要使用从 Object.prototype 继承而来的 hasOwnProperty 方法. hasOwnProperty 方法是 JavaScr ...
- 细说JavaScript对象(1):对象的使用和属性
JavaScript 中的一切都可以视为对象,除了两个特例:null 和 undefined. false.toString(); // 'false' [1, 2, 3].toString(); / ...
- 10 JavaScript对象&类&for循环
JavaScript对象 JavaScript中所有事物都是对象:字符串.数值.数组.函数.数学和正则表达式 JavaScript有些类型可以是字面量而非对象:如字符串.数值.布尔值 JavaScri ...
- 细说JavaScript单线程的一些事
标签: JavaScript 单线程 首发地址:码农网<细说JavaScript单线程的一些事> 最近被同学问道 JavaScript 单线程的一些事,我竟回答不上.好吧,感觉自己的 Ja ...
- 简述JavaScript对象、数组对象与类数组对象
问题引出 在上图给出的文档中,用JavaScript获取那个a标签,要用什么办法呢?相信第一反应一定是使用document.getElementsByTagName('a')[0]来获取.同样的,在使 ...
- 深入理解javascript对象系列第二篇——属性操作
× 目录 [1]查询 [2]设置 [3]删除[4]继承 前面的话 对于对象来说,属性操作是绕不开的话题.类似于“增删改查”的基本操作,属性操作分为属性查询.属性设置.属性删除,还包括属性继承.本文是对 ...
- Javascript并发模型和事件循环
Javascript并发模型和事件循环 JavaScript的"并发模型"是基于事件循环的,这个并发模型有别于Java的多线程, javascript的并发是单线程的. Javas ...
- web前端学习(二) javascript对象和原型继承
目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...
随机推荐
- Linux 内核数据结构bitmap
#include <stdio.h> #include <stdlib.h> #define MAX_PRIO 10000 #define BITS_PER_LONG 32 # ...
- hdu 1085 给出数量限制的母函数问题 Holding Bin-Laden Captive!
Holding Bin-Laden Captive! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...
- 【bzoj3436】小K的农场 差分约束系统+最长路-Spfa
原文地址:http://www.cnblogs.com/GXZlegend/p/6801470.html 题目描述 背景 小K是个特么喜欢玩MC的孩纸... 描述 小K在MC里面建立很多很多的农场,总 ...
- 修复linux密码
To reset the root password of your server, you will need to boot into single user mode. Access the M ...
- 算法复习———dijkstra求次短路(poj3255)
题目: Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her ...
- Tomcat学习笔记(十二)
Host和Engine容器 Context容器的父容器通常是Host容器. Engine容器表示Catalina的整个servlet引擎.如果使用Engine容器,那么它总是处于容器层级的最顶层.默认 ...
- java中TCP总结
先看一张图,画的很挫,将就看. TCP 客户端与服务端通信时,是服务端会拿到客户端的socket进行通信. TCP就相当于以前的座机,有一个听筒和一个话筒,A用话筒说话,B用听筒听. 下面讲讲java ...
- 《c程序设计语言》读书笔记-4.13-递归版本reverse函数
#include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> ...
- linux进程服务监测流程
进程->端口监听->查阿里云端口开放->看防火墙 ps -ef | grep redis ->netstat -an |grep redis->安全组设置端口放行规则 ...
- jQuery遍历文档(重要)
什么是遍历? jQuery 遍历,意为"移动",用于根据其相对于其他元素的关系来"查找"(或选取)HTML 元素.以某项选择开始,并沿着这个选择移动,直到抵达您 ...