持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
在查看ES5/6里面新的遍历语法的时候,会发现两个比较相近的语法
for-in和for-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则因为加入标准较晚,需要使用的话,对浏览器的版本还是有一定的要求,详细支持情况可以参考下图。