for
for in
for...in主要用于循环遍历对象的可枚举属性。如果用于数组,他遍历的是数组的索引
js
const sym = Symbol('demo')
const proto = {
protoProp: 'proto value'
}
const obj = Object.create(proto)
obj.ownProp = 'own value'
obj[sym] = 'symbol'
Object.defineProperty(obj, 'nonEnumProp', {
value: 'nonEnumerable value',
enumerable: false
})
const result = []
for (let key in obj) {
result.push(key)
}
const ownResult = []
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
ownResult.push(key)
}
}
console.log(result) // [ 'ownProp', 'protoProp' ] 包含了原型链上的属性
console.log(ownResult) // [ 'ownProp' ]
console.log(Object.keys(obj)) // [ 'ownProp' ]
console.log(Reflect.ownKeys(obj)) // [ 'ownProp', 'nonEnumProp', Symbol(demo) ]- 它返回的是字符串类型的键名(即使是数字索引也是字符串
"0") - 它会遍历对象原型链上新增的属性,这在遍历数组是通常会导致意外的错误
for in会遍历原型链,如果只想遍历对象自身的可枚举字符串属性,务必搭配hasOwnProperty
for of
for...of是ES6引入的语法,专门用于遍历可迭代对象
js
const list = ['a', 'b', 'c']
list.name = 'my-list'
for (let value of list) {
console.log(value) // 输出: "a", "b", "c"
}- 它只官族数据本身,不会去管自定义属性或原型链上的东西
- 普通对象不能直接用
for...of遍历,因为对象默认没有实现Symbol.iterator接口(会报错TypeError),需要先实现迭代协议
为什么对象不能用for...of
for...of依赖于对象内部的Iterator(迭代器)。数组、Map、Set内部都原生实现了这个接口,但Object没有 如果想用for...of遍历普通对象,可以用以下方法
Object.keys(obj):遍历键Object.values(obj):遍历值Object.entries(obj):遍历键值对