在实际开发中,我们经常需要访问一个对象的每一个属性,例如检查每一个配置项,或者处理每一个用户信息,此时可以使用 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。
