Skip to content

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(迭代器)。数组、MapSet内部都原生实现了这个接口,但Object没有 如果想用for...of遍历普通对象,可以用以下方法

  • Object.keys(obj):遍历键
  • Object.values(obj):遍历值
  • Object.entries(obj):遍历键值对