for-in vs. for-of

107 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

在查看ES5/6里面新的遍历语法的时候,会发现两个比较相近的语法for-infor-of。从文字上看,一时之间很难分辨出两者之间有什么区别。

for-in

语法

for (variable in object) {
    statement
}

for-in语法是在ES5引入的,提供一个便捷的方式去遍历获取对象的属性名(key)。

for-in具有以下的特点:

  • 获取的是对象的可枚举的字符串类型的属性名
  • 遍历自身和继承于原型链上的属性,原型链上越接近的越优先遍历
  • 遍历的对象如果存在整形的属性名,会优先遍历整型的属性名,然后遍历其他属性名
  • 可在遍历过程中使用continue提前进入下一次遍历和break跳出遍历流程

参考代码:

const object = {
  a: 1,
  b: 2,
  c: 3
}
object[0] = '2333'
object.foo = '666'
Object.defineProperties(object, {
    nonEnumFoo: {
        value: 'nonono',
        enumerable: false,
        writable: true
    }
})

for (const property in object) {
  console.log(`${property}: ${object[property]}`)
}

console.log('==========')

const arr = ['x', 'y', 'z']
arr.foo = 'blabla'

for (const property in arr) {
  console.log(`${property}: ${arr[property]}`)
}

console.log('==========')

function Sub() {
  this.type = 'Sub-Object'
}

Sub.prototype = object

const sub = new Sub()
sub[1] = '555'

for (const property in sub) {
  console.log(`${property}: ${sub[property]}`)
}
0: 2333
a: 1
b: 2
c: 3
foo: 666
==========
0: x
1: y
2: z
foo: blabla
==========
1: 555
type: Sub-Object
0: 2333
a: 1
b: 2
c: 3
foo: 666

有上面的特点和参考代码可知:

  • for-in会遍历原型链上的属性
  • 数组对象会遍历索引以外的的其他属性

这两点可能在实际使用中不符合我们的期望,需要进行额外的处理和过滤。

例如使用myObj.hasOwnProperty()或者Object.keys(myObj)去获取只属于当前对象的属性名。

for-of

语法

for (variable of iterable_object) {
    statement
}

for-of语法是在ES6引入的,针对可遍历(迭代)对象,提供一个便捷的方式去遍历获取其属性值(value)。

for-of具有以下的特点:

  • 非可遍历对象执行时会报错(如对象)
  • 获取的是可遍历对象的可遍历的属性值
  • 可在遍历过程中使用continue提前进入下一次遍历和break跳出遍历流程

有上面的特点可知,能执行for-of的对象必须是可迭代的,常见的Javascript内置的可迭代对象包括:

  • Array
  • String
  • TypedArray
  • Map
  • Set
  • NodeList
  • arguments

参考代码:

const arr = ['x', 'y', 'z']
arr.foo = 'blabla'

for (const val of arr) {
  console.log(val)
}

console.log('==========')

const obj = {
  a: 1,
  b: false
}

for (const val of obj) {
  console.log(val)
}
x
y
z
==========
Uncaught TypeError: obj is not iterable

兼容性

for-in由于加入标准的时间比较长,目前市面上绝大多数的现代浏览器都能很好的支持。

for-of则因为加入标准较晚,需要使用的话,对浏览器的版本还是有一定的要求,详细支持情况可以参考下图。

Screen Shot 2022-10-07 at 8.44.32 PM.png