JavaScript探秘:for-in循环(for-in Loops)
2011-05-04 00:00
916 查看
for-in循环应该用在非数组对象的遍历上,使用for-in进行循环也被称为“枚举”。
从技术上将,你可以使用for-in循环数组(因为JavaScript中数组也是对象),但这是不推荐的。因为如果数组对象已被自定义的功能增强,就可能发生逻辑错误。另外,在for-in中,属性列表的顺序(序列)是不能保证的。所以最好数组使用正常的for循环,对象使用for-in循环。
有个很重要的hasOwnProperty()方法,当遍历对象属性的时候可以过滤掉从原型链上下来的属性。
思考下面一段代码:
在这个例子中,我们有一个使用对象字面量定义的名叫man的对象。在man定义完成后的某个地方,在对象原型上增加了一个很有用的名叫 clone()的方法。此原型链是实时的,这就意味着所有的对象自动可以访问新的方法。为了避免枚举man的时候出现clone()方法,你需要应用hasOwnProperty()方法过滤原型属性。如果不做过滤,会导致clone()函数显示出来,在大多数情况下这是不希望出现的。
另外一种使用hasOwnProperty()的形式是取消Object.prototype上的方法。像这样:
其好处在于在man对象重新定义hasOwnProperty情况下避免命名冲突。也避免了长属性查找对象的所有方法,你可以使用局部变量“缓存”它。
严格来说,不使用hasOwnProperty()并不是一个错误。根据任务以及你对代码的自信程度,你可以跳过它以提高些许的循环速度。但是当你对当前对象内容(和其原型链)不确定的时候,添加hasOwnProperty()更加保险些。
格式化的变化(通不过JSLint)会直接忽略掉花括号,把if语句放到同一行上。其优点在于循环语句读起来就像一个完整的想法(每个元素都有一个自己的属性”X”,使用”X”干点什么):
我们应该如何去了解JavaScript引擎的工作原理
JavaScript探秘:编写可维护的代码的重要性
JavaScript探秘:谨慎使用全局变量
JavaScript探秘:var预解析与副作用
JavaScript探秘:for循环(for Loops)
JavaScript探秘:for-in循环(for-in Loops)
JavaScript探秘:Prototypes强大过头了
JavaScript探秘:eval()是“魔鬼”
JavaScript探秘:用parseInt()进行数值转换
JavaScript探秘:基本编码规范
JavaScript探秘:函数声明与函数表达式
JavaScript探秘:命名函数表达式
JavaScript探秘:调试器中的函数名
JavaScript探秘:JScript的Bug
JavaScript探秘:JScript的内存管理
JavaScript探秘:SpiderMonkey的怪癖
JavaScript探秘:命名函数表达式替代方案
JavaScript探秘:对象Object
JavaScript探秘:原型链 Prototype chain
JavaScript探秘:构造函数 Constructor
JavaScript探秘:可执行的上下文堆栈
执行上下文其一:变量对象与活动对象
执行上下文其二:作用域链 Scope Chains
执行上下文其三:闭包 Closures
执行上下文其四:This指针
JavaScript探秘:强大的原型和原型链
JavaScript函数其一:函数声明
JavaScript函数其二:函数表达式
JavaScript函数其三:分组中的函数表达式
JavaScript函数其四:函数构造器
JavaScript变量对象其一:VO的声明
JavaScript变量对象其二:VO在不同的执行上下文中
JavaScript变量对象其三:执行上下文的两个阶段
JavaScript变量对象其四:关于变量
JavaScript变量对象其五:__parent__ 属性
JavaScript作用域链其一:作用域链定义
JavaScript作用域链其二:函数的生命周期
JavaScript作用域链其三:作用域链特征
JavaScript闭包其一:闭包概论
JavaScript闭包其二:闭包的实现
JavaScript闭包其三:闭包的用法
从技术上将,你可以使用for-in循环数组(因为JavaScript中数组也是对象),但这是不推荐的。因为如果数组对象已被自定义的功能增强,就可能发生逻辑错误。另外,在for-in中,属性列表的顺序(序列)是不能保证的。所以最好数组使用正常的for循环,对象使用for-in循环。
有个很重要的hasOwnProperty()方法,当遍历对象属性的时候可以过滤掉从原型链上下来的属性。
思考下面一段代码:
// 对象 var man = { hands: 2, legs: 2, heads: 1 }; // 在代码的某个地方 // 一个方法添加给了所有对象 if (typeof Object.prototype.clone === "undefined") { Object.prototype.clone = function () {}; }
在这个例子中,我们有一个使用对象字面量定义的名叫man的对象。在man定义完成后的某个地方,在对象原型上增加了一个很有用的名叫 clone()的方法。此原型链是实时的,这就意味着所有的对象自动可以访问新的方法。为了避免枚举man的时候出现clone()方法,你需要应用hasOwnProperty()方法过滤原型属性。如果不做过滤,会导致clone()函数显示出来,在大多数情况下这是不希望出现的。
// 1. // for-in 循环 for (var i in man) { if (man.hasOwnProperty(i)) { // 过滤 console.log(i, ":", man[i]); } } /* 控制台显示结果 hands : 2 legs : 2 heads : 1 */ // 2. // 反面例子: // for-in loop without checking hasOwnProperty() for (var i in man) { console.log(i, ":", man[i]); } /* 控制台显示结果 hands : 2 legs : 2 heads : 1 clone: function() */
另外一种使用hasOwnProperty()的形式是取消Object.prototype上的方法。像这样:
for (var i in man) { if (Object.prototype.hasOwnProperty.call(man, i)) { // 过滤 console.log(i, ":", man[i]); } }
其好处在于在man对象重新定义hasOwnProperty情况下避免命名冲突。也避免了长属性查找对象的所有方法,你可以使用局部变量“缓存”它。
var i, hasOwn = Object.prototype.hasOwnProperty; for (i in man) { if (hasOwn.call(man, i)) { // 过滤 console.log(i, ":", man[i]); } }
严格来说,不使用hasOwnProperty()并不是一个错误。根据任务以及你对代码的自信程度,你可以跳过它以提高些许的循环速度。但是当你对当前对象内容(和其原型链)不确定的时候,添加hasOwnProperty()更加保险些。
格式化的变化(通不过JSLint)会直接忽略掉花括号,把if语句放到同一行上。其优点在于循环语句读起来就像一个完整的想法(每个元素都有一个自己的属性”X”,使用”X”干点什么):
// 警告: 通不过JSLint检测 var i, hasOwn = Object.prototype.hasOwnProperty; for (i in man) if (hasOwn.call(man, i)) { // 过滤 console.log(i, ":", man[i]); }
延伸阅读
此文章所在专题列表如下:我们应该如何去了解JavaScript引擎的工作原理
JavaScript探秘:编写可维护的代码的重要性
JavaScript探秘:谨慎使用全局变量
JavaScript探秘:var预解析与副作用
JavaScript探秘:for循环(for Loops)
JavaScript探秘:for-in循环(for-in Loops)
JavaScript探秘:Prototypes强大过头了
JavaScript探秘:eval()是“魔鬼”
JavaScript探秘:用parseInt()进行数值转换
JavaScript探秘:基本编码规范
JavaScript探秘:函数声明与函数表达式
JavaScript探秘:命名函数表达式
JavaScript探秘:调试器中的函数名
JavaScript探秘:JScript的Bug
JavaScript探秘:JScript的内存管理
JavaScript探秘:SpiderMonkey的怪癖
JavaScript探秘:命名函数表达式替代方案
JavaScript探秘:对象Object
JavaScript探秘:原型链 Prototype chain
JavaScript探秘:构造函数 Constructor
JavaScript探秘:可执行的上下文堆栈
执行上下文其一:变量对象与活动对象
执行上下文其二:作用域链 Scope Chains
执行上下文其三:闭包 Closures
执行上下文其四:This指针
JavaScript探秘:强大的原型和原型链
JavaScript函数其一:函数声明
JavaScript函数其二:函数表达式
JavaScript函数其三:分组中的函数表达式
JavaScript函数其四:函数构造器
JavaScript变量对象其一:VO的声明
JavaScript变量对象其二:VO在不同的执行上下文中
JavaScript变量对象其三:执行上下文的两个阶段
JavaScript变量对象其四:关于变量
JavaScript变量对象其五:__parent__ 属性
JavaScript作用域链其一:作用域链定义
JavaScript作用域链其二:函数的生命周期
JavaScript作用域链其三:作用域链特征
JavaScript闭包其一:闭包概论
JavaScript闭包其二:闭包的实现
JavaScript闭包其三:闭包的用法
相关文章推荐
- JavaScript探秘:for-in循环(for-in Loops)
- javascript之for-in循环(for-in Loops)
- JavaScript中的for in 循环
- JavaScript 中 for (var i in data) 循环数组项
- javascript 循环语句 while、do-while、for-in、for用法区别
- JavaScript for...in循环
- JavaScript for...in循环
- JavaScript中for..in循环陷阱介绍
- for-in循环(for-in Loops)
- JavaScript for...in循环
- Effective JavaScript Item 49 对于数组遍历,优先使用for循环,而不是for..in循环
- javascript for/in 循环遍历对象属性
- 全面解析JavaScript里的循环方法之forEach,for-in,for-of
- javascript中关键字in以及循环for...in的使用和注意事项
- 跟我学习javascript的for循环和for...in循环
- 你不知道的JavaScript--Item16 for 循环和for...in 循环的那点事儿
- javaScript循环总结(for,for-in,for-of,forEach,map,filter,every,reduce,reduceRight)
- JavaScript for...in 循环的陷阱
- 你不知道的JavaScript--Item16 for 循环和for...in 循环的那点事儿
- JavaScript里的循环方法:forEach,for-in,for-of