Lasy

前端开发攻城狮~

JavaScript for...in 和 for...of的区别

定义

for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。
for...of语句在可迭代对象(包括 ArrayMapSetStringTypedArrayarguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句

区别

  1. for...in遍历的是属性;for...of遍历的是值(一般来讲)。
  2. for...in可以遍历所有对象;for...of只能遍历 可迭代对象
  3. for...in语句以 原始插入顺序 遍历对象的 可枚举属性for...of语句不能保证遍历顺序,但是可以遍历到不可枚举属性。

可迭代对象

遍历可迭代对象:

for...of遍历值,for...in遍历属性。

遍历不可迭代对象:

我们自己定义的obj没有遍历接口,是不可迭代对象,使用for...of会报错;
但是使用for...in可以遍历到obj的可枚举属性。

接下来我们给obj增加遍历接口:

可以看到,现在使用for...of也可以遍历obj了。
你应该已经注意到,for...of遍历到的并不是obj的值,for...of遍历结果取决于遍历接口如何定义,也就是obj[Symbol.iterator]ArrayMapSetStringTypedArrayarguments 对象等等已经原生定义了遍历接口。
obj[Symbol.iterator]执行后返回一个迭代器,for...of遍历的原理就是对这个迭代器的遍历。
for (const value of obj) {...}相当于for (const value of obj[Symbol.iterator]()) {...}

可迭代对象本身就具备遍历器接口,遍历器接口定义了for...of如何遍历。

例子中,我们修改了数组的遍历器接口,因此使用for...of时按照我们定义的方式遍历了数组。

可枚举属性

for...in只能遍历可枚举属性。

可枚举属性是指那些内部 “可枚举” 标志设置为 true 的属性,对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true,对于通过 Object.defineProperty 等定义的属性,该标识值默认为 false

判断方法:Object.prototype.propertyIsEnumerable()Object.keys()中含有。

可以看到,对于不可枚举的属性unenumerableObject.keys()中并不存在,for..in也不能遍历。

参考:

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注