for...in

for...in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性。

语法

for (variable in object)
  statement
variable
在每次迭代时,variable会被赋值为不同的属性名。
object
非Symbol类型的可枚举属性被迭代的对象。

数组迭代和 for...in

提示:for...in不应该用于迭代一个 Array,其中索引顺序很重要。

仅迭代自身的属性

如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性(也能使用propertyIsEnumerable)。或者,如果你知道不会有任何外部代码干扰,您可以使用检查方法扩展内置原型。

为什么用for ... in?

for ... in是为遍历对象属性而构建的,不建议与数组一起使用,数组可以用Array.prototype.forEach()for ... of,那么for ... in的到底有什么用呢?

它最常用的地方应该是用于调试,可以更方便的去检查对象属性(通过输出到控制台或其他方式)。尽管对于处理存储数据,数组更实用些,但是你在处理有key-value数据(比如属性用作“键”),需要检查其中的任何键是否为某值的情况时,还是推荐用for ... in

示例

下面的函数接受一个对象作为参数。被调用时迭代传入对象的所有可枚举属性然后返回一个所有属性名和其对应值的字符串。

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 (ECMA-262)
for...in statement
Living Standard
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.

浏览器兼容

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
for...inChrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 6Opera Full support 2Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100

Legend

Full support  
Full support

兼容性:初始化函数表达式

在 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) 正在研究去除这种不标准的行为。

相关链接