JavaScript for...in 循环

在实际开发中,我们经常需要访问一个对象的每一个属性,例如检查每一个配置项,或者处理每一个用户信息,此时可以使用 for...in 循环来实现。

什么是 for...in 循环?

在 JavaScript 中,我们可以使用 for...in 循环用于遍历对象的可枚举属性,包括对象自身的可枚举属性,以及它原型链上继承的可枚举属性。在循环的每一次迭代中,都会将一个属性名(键)赋值给指定的变量。

语法:

for (let key in obj) {
    ……
}

说明:

在循环的内部,我们可以使用 key 访问属性名,也可以使用 obj[key] 访问属性值。

注意:

  • for...in 循环在每次迭代时,会将对象的属性名(键)赋值给变量 key。也就是说变量 key 在每次迭代时都会被重新赋值,此时应该使用 let 来声明,而不能使用 const 来声明。
  • for...in 循环在遍历对象的属性时,不保证顺序。因此,如果对顺序有严格要求(比如数组),请不要使用 for...in。

示例 1:使用 for...in 遍历对象属性

const person = {
    "name": "阿莫",
    "age": 20,
    "city": "广州"
};

for (let key in person) {
    console.log("属性名:" + key + ",属性值:" + person[key]);
}

运行结果如下。

属性名:name,属性值:阿莫
属性名:age,属性值:20
属性名:city,属性值:广州

分析:

在这个例子中,for...in 循环遍历了 person 对象的 3 个自身属性 "name"、"age" 和 "city"。在每次迭代中,key 变量会依次取到这些属性名,然后我们通过 person[key] 访问到对应的属性值。

for...in 会遍历继承属性

在 JavaScript 中,for...in 循环非常重要的一个特点是:它不仅会遍历对象自身的属性,还会遍历对象原型链上继承的可枚举属性

示例 2:for...in 会遍历继承属性

const animal = {
    "type": "中华田园犬"
};

// dog 继承自 animal
const dog = Object.create(animal);
dog.name = "大黄";

for (let key in dog) {
    console.log("属性:" + key + ",值:" + dog[key]);
}

运行结果如下。

属性:name,值:大黄
属性:type,值:中华田园犬

分析:

从结果可以看出,for...in 循环不仅遍历了 dog 自身的属性 "name",还遍历了从 animal 原型继承而来的属性 "type"。在某些情况下,这可能不是我们想要的结果。

如何只遍历自身属性?

为了避免 for...in 遍历到继承属性,我们通常会在循环的内部使用 hasOwnProperty() 方法来判断属性是否是对象自身属性。

语法:

for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
        ……
    }
}

说明:

obj.hasOwnProperty(key) 可以用于判断 key 是否是 obj 自身的属性。

而使用 Object.prototype.hasOwnProperty.call(obj, key) 这种方式更加安全,它可以防止对象覆盖了原生的 hasOwnProperty() 方法。

不过在实际开发中,大多数情况下,我们使用 obj.hasOwnProperty(key) 已经够了。

示例 3:for...in 配合 hasOwnProperty()

const animal = {
    "type": "中华田园犬"
};

// dog 继承自 animal
const dog = Object.create(animal);
dog.name = "大黄";

for (let key in dog) {
    if (dog.hasOwnProperty(key)) { 
        console.log("自身属性:" + key + ",值:" + dog[key]);
    } else {
        console.log("继承属性:" + key + ",值:" + dog[key]);
    }
}

运行结果如下。

自身属性:name,值:大黄
继承属性:type,值:中华田园犬

分析:

这个例子中,dog 对象自身有一个 name 属性,并继承了 animal 的 type 属性。使用 hasOwnProperty(key) 可以判断当前的 key 是否是 dog 对象自身的属性,从而避免遍历到继承属性。

for...in 与 for...of 的区别

很多初学的小伙伴容易把 for...in 与 for...of 这两个搞混,实际上它们有着本质上的区别。

  • for...in:用于遍历对象的属性名。
  • for...of:用于遍历可迭代对象(如数组、字符串、Map、Set 等)的元素值。

示例 4:for...in 遍历数组

const arr = ["red", "green", "blue"]; 

for (let key in arr) {
    console.log(key);
}

运行结果如下。

0
1
2

分析:

数组本质上也是一个对象,而 for...in 会遍历对象的属性名。当我们使用 for...in 遍历数组时,本质上遍历的是数组的索引(属性名)。

示例 5:for...of 遍历数组

const arr = ["red", "green", "blue"]; 

for (let value of arr) {
    console.log(value);
}

运行结果如下。

red
green
blue

分析:

for...of 遍历的是数组的元素值。通常情况下,遍历数组应该使用 for 循环forEach() 方法或 for...of,而不是 for...in。

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号