在本教程中,您将学习如何使用 JavaScrip tfor...in 循环迭代对象的可枚举属性。

JavaScript for...in 循环简介

遍历以对象字符串为键的可枚举属性。请注意,属性可以由字符串或符号作为键。

for...in 循环可通过对象的键,迭代对象的属性。对象的键可以是字符串或者是一个符号

当一个属性是通过简单的赋值或者使用属性初始化器创建时,属性的数据属性 enumerable 默认是 true

object.propertyName = value;

或者

let obj = {
    propertyName: value,
    ...
};

下面展示 for...in 循环的语法:

for(const propertyName in object) {
    // ...
}

for...in 循环允许您在不知道属性的名称的情况访问对象的每个属性和值。例如:

var person = {
    firstName: 'John',
    lastName: 'Doe',
    ssn: '299-24-2351'
};

for(var prop in person) {
    console.log(prop + ':' + person[prop]);
}

输出:

firstName:John
lastName:Doe
ssn:299-24-2351

在这个例子,我们使用 for...in 循环迭代 person 对象的属性。我们使用以下语法访问每个属性的值:

object[property]; 

for...in 循环与继承

当您遍历已继承其它对象的属性时,for...in 语句在原型链中上升并枚举继承的属性。比如以下示例:

var decoration = {
    color: 'red'
};

var circle = Object.create(decoration);
circle.radius = 10;


for(const prop in circle) {
    console.log(prop);
}

输出:

radius
color

circle 对象原型引用 decoration 对象。因此,for...in 循环打印 circle 对象及其原型的属性。

如果只想枚举对象自身的属性,可以使用 hasOwnProperty() 方法:

for(const prop in circle) {
    if(circle.hasOwnProperty(prop)) {
        console.log(prop);
    }
}

输出:

radius

for...in 循环与数组

最好不要使用 for...in 循环遍历数组,尤其是当数组元素的顺序很重要时。以下示例很好地运行:

const items = [10 , 20, 30];
let total = 0;

for(const item in items) {
    total += items[item];
}
console.log(total); 

但是,有人可能会在他们的库中设置内置 Array 类型的属性,如下所示:

Array.prototype.foo = 100;

因此,for...in 将无法正常工作。例如:

Array.prototype.foo = 100;

const items = [10, 20, 30];
let total = 0;

for (var prop in items) {
  console.log({ prop, value: items[prop] });
  total += items[prop];
}
console.log(total);

输出:

{ prop: '0', value: 10 }
{ prop: '1', value: 20 }
{ prop: '2', value: 30 }
{ prop: 'foo', value: 100 }
160

或者另一个例子:

var arr = [];
// set the third element to 3, other elements are `undefined`
arr[2] = 3; 

for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);    
}

输出显示数组的三个元素,这是正确的:

undefined
undefined
3

但是, for...in 循环忽略了前两个元素:

for (const key in arr) {
    console.log(arr[key]);
}

输出:

3

输出仅显示第三个元素,不显示前两个元素。

结论

  • for...in 循环遍历对象的可枚举属性。它还会上升到原型链并枚举继承的属性。
  • 避免使用 for...in 循环遍历数组的元素,尤其是当索引顺序很重要时。