for...in
语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。
语法
for (variable in object) {...}
- 在每次迭代时,将不同的属性名分配给 变量。
variable
- 被迭代枚举其属性的对象。
object
描述
for...in
循环只遍历可枚举属性。像 Array
和 Object
使用内置构造函数所创建的对象都会继承自Object.prototype
和String.prototype
的不可枚举属性,例如 String
的 indexOf()
方法或 Object
的toString()
方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。
删除,添加或者修改属性
for...in
循环以任意序迭代一个对象的属性(请参阅delete
运算符,了解为什么不能依赖于迭代的表面有序性,至少在跨浏览器设置中)。如果一个属性在一次迭代中被修改,在稍后被访问,其在循环中的值是其在稍后时间的值。一个在被访问之前已经被删除的属性将不会在之后被访问。在迭代进行时被添加到对象的属性,可能在之后的迭代被访问,也可能被忽略。通常,在迭代过程中最好不要在对象上进行添加、修改或者删除属性的操作,除非是对当前正在被访问的属性。这里并不保证是否一个被添加的属性在迭代过程中会被访问到,不保证一个修改后的属性(除非是正在被访问的)会在修改前或者修改后被访问,不保证一个被删除的属性将会在它被删除之前被访问。
数组迭代和 for...in
提示:for...in
不应该用于迭代一个 Array
,其中索引顺序很重要。
数组索引只是具有整数名称的枚举属性,并且与通用对象属性相同。不能保证for ... in
将以任何特定的顺序返回索引。for ... in
循环语句将返回所有可枚举属性,包括非整数类型的名称和继承的那些。
因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行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(`obj.${prop} = ${obj[prop]}`);
}
}
// Output:
// "obj.color = red"
规范
Specification | Status | Comment |
---|---|---|
ECMAScript Latest Draft (ECMA-262) for...in statement | Draft | |
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 | Initial definition. |
兼容性:初始化函数表达式
在 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及更高版本中被忽略,并将在严格模式(bug 748550 和 bug 1164741)中呈现SyntaxError
("for-in loop head declarations may not have initializers")错误。
像其他引擎 V8(Chrome),Chakra (IE/Edge), JSC (WebKit/Safari) 正在研究去除这种不标准的行为。