for…in和for…of的区别

223 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

js中对数组和对象循环遍历的方法有很多,常见的有for、forEach、for…in、for…of,也有封装的API用于遍历数组和对象,如filter、map、reduce、some、every等,只是不同的api处理对象的能力以及返回的数据不一样。本文主要针对for…in和for…of,简单谈谈两者的区别。

总的来说,for…in可用于遍历可枚举的数据,例如对象、数组、字符串等,for…of可用于遍历可迭代的数据,例如数组、对象、字符串、Map、Set等。

可枚举

可枚举是指对象内属性的可枚举标志enumerable为true,此属性不包括symbol。常见的可枚举对象有字符串、数组、对象等,例如:

let obj = 'obj'; // 字符串
console.log(Object.getOwnPropertyDescriptors(obj)[0].enumerable); // true
obj = [1,2,3]; // 数组
console.log(Object.getOwnPropertyDescriptors(obj)[0].enumerable); // true
obj = {x: 10}; // 对象
console.log(Object.getOwnPropertyDescriptors(obj)['x'].enumerable); // true

可迭代

可迭代对象是指一个对象实现了@@iterator方法,可通过常量Symbol.iterator判断对象内是否有@@iterator属性。常见的数组、Map、Set、字符串、arguments、generator等,例如:

let obj = '123'; // 字符串
console.log(typeof obj[Symbol.iterator]) // function
obj = [1,2,3]; // 数组
console.log(typeof obj[Symbol.iterator]) // function
obj = new Set([1,2,3]); // Set
console.log(typeof obj[Symbol.iterator]) // function
obj = new Map([['x',1],['y',2]]); // Map
console.log(typeof obj[Symbol.iterator]) // function
obj = {x:100}; // 对象
console.log(typeof obj[Symbol.iterator]) // undefined,对象不是可迭代

for…in

用于遍历可枚举数据,包括字符串、数组、对象,得到的是key值或者下标值,不管是key还是下标值,得到的都是字符串类型。遍历顺序不一定是数据内实际的排列顺序。

let obj = [1,2,3]; // 数组
for (let i in obj) {
  console.log(typeof i); // string
}
obj = {x:10,y:20}; // 对象
for (let i in obj) {}

for…of

用于遍历可迭代数据,包括字符串、数组、Map、Set等,注意不包括对象,得到的是可迭代数据的值。如果要遍历对象,则只能通过for…in,或者使用Object.keys()先获取对象的所有key的数组,然后再使用for…of遍历,其实也是遍历的数组。

let obj = [1,2,3]; // 数组
for (let i of obj) {
  console.log(i, typeof i); // value, number
}
obj = {
  x: 10,
  y: 20
}
for (let k of Object.keys(obj)) {
  console.log(k, obj[k]); // key,value
}

结语

for…in和for…of虽然看起来比较像,用法也类似,但是在具体的使用场景上面还是有所不同,关键在于是可枚举数据还是可迭代数据。

  • for…in可遍历对象,for…of不可以
  • for…in可遍历数组原型链上的属性,包括手动添加的属性,但是for…of不可以
  • for…in和for…of都可以遍历数组、字符串,大多数场景两者是等价的。
  • for…in和for…of都可break当前循环

原创不易,转载请注明出处