for...in
语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。
语法
for (variable in object) {...}
参数
variable
- 在每次迭代时,将不同的属性名分配给变量。
object
- 被迭代枚举其属性的对象。
描述
for...in
循环只遍历可枚举属性。像 Array 和 Object 使用内置构造函数所创建的对象都会继承自 Object.prototype 和 String.prototype 的不可枚举属性,例如 String
的
indexOf()
方法或者 Object 的
toString
方法。循环将迭代对象的所有可枚举属性和从它的构造函数的 prototype 继承而来的(包括被覆盖的内建属性)。
删除,添加或者修改属性
for...in
循环以任意序迭代一个对象的属性(浏览 delete operator 了解更多关于为什么开发者不能依赖于“看上去”的迭代顺序,至少是在跨浏览器情况下)。 如果一个属性在一次迭代中被修改,在稍后被访问,其在循环中的值是其在稍后时间的值。一个在被访问之前已经被删除的属性将不会在之后被访问。在迭代进行时被添加到对象的属性,可能在之后的迭代被访问,也可能被忽略。通常,在迭代过程中最好不要在对象上进行添加、修改或者删除属性的操作,除非是对当前正在被访问的属性。这里并不保证是否一个被添加的属性在迭代过程中会被访问到,不保证一个修改后的属性(除非是正在被访问的)会在修改前或者修改后被访问,不保证一个被删除的属性将会在它被删除之前被访问。
Array 迭代和 for...in
Note: for..in
不应该被用来迭代一个下标顺序很重要的 Array
.
数组索引仅是可枚举的整数名,其他方面和别的普通对象属性没有什么区别。for...in 并不能够保证返回的是按一定顺序的索引,但是它会返回所有可枚举属性,包括非整数名称的和继承的。
因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。 因此当迭代那些访问次序重要的 arrays 时用整数索引去进行 for
循环 (或者使用 Array.prototype.forEach()
或 for...of
循环) 。
仅迭代自身的属性
如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames()
或执行 hasOwnProperty()
来确定某属性是否是对象本身的属性 (也能使用propertyIsEnumerable
)。另外,如果你知道外部不存在任何的干扰代码,你可以扩展内置原型与检查方法。
例子
下面的函数接受一个对象作为参数。被调用时迭代传入对象的所有可枚举属性然后返回一个所有属性名和其对应值的字符串。
var obj = {a:1, b:2, c:3}; for (var prop in obj) { console.log("obj." + prop + " = " + obj[prop]); } // Output: // "obj.a = 1" // "obj.b = 2" // "obj.c = 3"
下面的函数阐述了 hasOwnProperty()
的用法: 隐藏的继承属性将不会被显示。
var triangle = {a:1, b:2, c:3};
function ColoredTriangle() {
this.color = "red";
}
ColoredTriangle.prototype = triangle;
var obj = new ColoredTriangle();
for (var prop in obj) {
if( obj.hasOwnProperty( prop ) ) {
console.log("o." + prop + " = " + obj[prop]);
}
}
// Output:
// "o.color = red"
规范
规范 | 状态 | 批注 |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) for...in statement |
Standard | |
ECMAScript 5.1 (ECMA-262) for...in statement |
Standard | |
ECMAScript 3rd Edition (ECMA-262) for...in statement |
Standard | |
ECMAScript 1st Edition (ECMA-262) for...in statement |
Standard | Inital definition. |
浏览器兼容性
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
兼容性:初始化函数表达式
在 SpiderMonkey 40 (Firefox 40 / Thunderbird 40 / SeaMonkey 2.37) 版本之前, 有可能在使用一个初始化表达式 (i=0
) 在一个 for...in
循环中:
var obj = {a:1, b:2, c:3};
for(var i=0 in obj) {
console.log(obj[i]);
}
// 1
// 2
// 3
这种非标准的方式已经在40的版本之后被移除了. 现在开始它会在控制台里抛出一个 SyntaxError
("for-in loop head declarations may not have initializers") 警告。(bug 748550 以及 bug 1164741)。
像其他引擎 V8(Chrome),Chakra (IE/Edge), JSC (WebKit/Safari) 正在研究去除这种不标准的行为。
相关
for...of
一个类似的迭代属性值的语句for each in
一个类似的但是迭代的是对象的属性的值而不是其属性名字的语句 (过时的)for
- 迭代器和构造器 (uses the
for...in
syntax) - Enumerability and ownership of properties
Object.getOwnPropertyNames()
Object.prototype.hasOwnProperty()
Array.prototype.forEach()