如同 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对象(1):对象的使用和属性

细说JavaScript对象(2):原型对象

细说JavaScript对象(3):hasOwnProperty

细说JavaScript对象(4): for in 循环

细说JavaScript对象(4): for in 循环的更多相关文章

  1. 细说JavaScript对象(2):原型对象

    JavaScript 并没有类继承模型,而是使用原型对象 prototype 进行原型式继承. 尽管人们经常将此看做是 JavaScript 的一个缺点,然而事实上,原型式继承比传统的类继承模型要更加 ...

  2. 细说JavaScript对象(3):hasOwnProperty

    判断一个属性是定义在对象本身而不是继承自原型链,我们需要使用从 Object.prototype 继承而来的 hasOwnProperty 方法. hasOwnProperty 方法是 JavaScr ...

  3. 细说JavaScript对象(1):对象的使用和属性

    JavaScript 中的一切都可以视为对象,除了两个特例:null 和 undefined. false.toString(); // 'false' [1, 2, 3].toString(); / ...

  4. 10 JavaScript对象&类&for循环

    JavaScript对象 JavaScript中所有事物都是对象:字符串.数值.数组.函数.数学和正则表达式 JavaScript有些类型可以是字面量而非对象:如字符串.数值.布尔值 JavaScri ...

  5. 细说JavaScript单线程的一些事

    标签: JavaScript 单线程 首发地址:码农网<细说JavaScript单线程的一些事> 最近被同学问道 JavaScript 单线程的一些事,我竟回答不上.好吧,感觉自己的 Ja ...

  6. 简述JavaScript对象、数组对象与类数组对象

    问题引出 在上图给出的文档中,用JavaScript获取那个a标签,要用什么办法呢?相信第一反应一定是使用document.getElementsByTagName('a')[0]来获取.同样的,在使 ...

  7. 深入理解javascript对象系列第二篇——属性操作

    × 目录 [1]查询 [2]设置 [3]删除[4]继承 前面的话 对于对象来说,属性操作是绕不开的话题.类似于“增删改查”的基本操作,属性操作分为属性查询.属性设置.属性删除,还包括属性继承.本文是对 ...

  8. Javascript并发模型和事件循环

    Javascript并发模型和事件循环 JavaScript的"并发模型"是基于事件循环的,这个并发模型有别于Java的多线程, javascript的并发是单线程的. Javas ...

  9. web前端学习(二) javascript对象和原型继承

    目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...

随机推荐

  1. log4j配置打印mybatis的sql到控制台(复制)

    log4j.rootLogger=DEBUG, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender ...

  2. ComboBox列表自定义类保存数据

    之前没弄明白ComboBox还可以这样用. 先建一个ComboBox子项类,然后可以获取该项类做一些判断,关键是要重写ToString()方法. public class ComboItem { pu ...

  3. Oracle在登陆时被告知用户被锁,如何解决?

    在登陆时被告知test用户被锁 1.用dba角色的用户登陆,进行解锁,先设置具体时间格式,以便查看具体时间 SQL> alter session set nls_date_format=’yyy ...

  4. 网络战争 [KD-Tree+最小割树]

    题面 思路 首先吐槽一下: 这题是什么东西啊??出题人啊,故意拼题很有意思吗??还拼两个这么毒瘤的东西???? 10K代码了解一下???? 然后是正经东西 首先,本题可以理解为这样: 给定$n$个块, ...

  5. winform中key读取修改

    根据key name的名称读取value-----读取使用ConfigurationManager.AppSettings读取容易没读取到根目录中的key public string GetXml(s ...

  6. (poj)Sequence Median

    Description Given a sequence of N nonnegative integers. Let's define the median of such sequence. If ...

  7. 图表绘制工具--Matplotlib 3

    ''' [课程3.] 表格样式创建 表格视觉样式:Dataframe.style → 返回pandas.Styler对象的属性,具有格式化和显示Dataframe的有用方法 样式创建: ① Style ...

  8. <a></a>的href属性失效

    <a href="javascript:void(0);" class="close">关闭</a>

  9. DotNETCore 学习笔记 路由

    Route ------------------------------------------constraint------------------------------------------ ...

  10. 学习ExtJS4 常用控件

    ExtJS组件配置方式介绍 1.使用逗号分隔参数列表配置组件    首先来看一个简单的逗号分隔参数列表的例子.这个例子非常简单,它用来显示信息提示框. 2.使用Json对象配置组件  接下来看一个使用 ...