(自用面试题)for...in、for...of的区别是什么?

91 阅读2分钟
  1. for...of循环是ES6新增的遍历方法。
  2. for..in循环遍历得到key,for...of循环遍历得到value。
  3. for..in循环只能用于遍历可枚举的数据,for...of循环只能用来遍历可迭代的数据。

拓展:
一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for...of循环遍历它的成员;也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。for...of循环可以使用的范围包括字符串、数组、Set、Map、某些类数组对象(比如arguments对象、DOM NodeList对象)、Generator对象;对于普通的对象,for...of循环不能直接使用,会报错,必须部署了Iterator接口后才能使用。
对象之所以没有默认部署Iterator接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。不过,严格地说,对象部署遍历器接口并不是很必要,因为这时对象实际上被当作Map结构使用,ES5没有Map结构,而ES6原生提供了。一个对象如果要具备可被for...of循环调用的Iterator接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
eg:

const obj = {
  name: "abc",
  age: 18,
};

for(let val of obj) {
  console.log(val);// Uncaught TypeError: obj is not iterable
}

可枚举数据:字符串、对象、数组
可迭代数据:字符串、数组、Set、Map、arguments对象、DOM NodeList对象

是否可枚举:Object.getOwnPropertyDescriptors(obj)返回的对象中enumerable为true
是否可迭代:arr[Symbol.iterator]()返回值中有next()

for...in循环的缺点:

  1. 数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。
  2. for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
  3. 某些情况下,for...in循环会以任意顺序遍历键名。

总之,for...in循环主要是为遍历对象而设计的,不适用于遍历数组。

eg:

let arr = [357]; 
arr.foo = 'hello'; 

for (let i in arr) {   
console.log(i); // "0""1""2""foo" 
} 

for (let i of arr) {   
// for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性
console.log(i); //  "3""5""7" 
}

拓展问题:
(自用面试题)for await...of的作用是什么?