for in 和 for of 是js中常用的遍历方法。但是两者有什么区别呢?

for infor of 是js中常用的遍历方法。但是两者有什么区别呢?
今天我们就来讨论下两者的区别。

遍历数组

  1. for in 是ES5的语法标准,而for of则是ES6语法标准。
const arr = ['a', 'b', 'c']
for(let i in arr){
    console.log(i)
    // '0', '1', '2'
}
for(let i of arr){
    console.log(i)
    // a, b, c
}

通过上述代码我们可以发现for in遍历的是下标,而for of遍历的是属性值
而且。for in所遍历的下标是Strign类型而不是Number类型。

  1. for in 遍历时可以遍历到当前数组的所有属性名和方法名。包括其原型链上定义的属性名和方法名。如下代码:
const arr = ['a', 'b', 'c']
arr.name = 'arr'
arr.getName =  function(){
  return this.name
}
arr.__proto__.constructor.prototype.sayHello = function(){
  return 'hello'
}
arr.__proto__.constructor.prototype.parentName = 'say uncle'
for(let i in arr){
  if(arr.hasOwnProperty(i)){
    console.log('ownProperty',i)
    // '0', '1', '2', 'name', 'getName'
  }else{
    console.log('not ownProperty',i)
    // 'sayHello', 'parentName'
  }
}

而使用for of遍历时则不会遍历原型链上的属性和方法且不会遍历定义在数组上的属性和方法。
代码如下:

const arr = ['a', 'b', 'c']
arr.name = 'arr'
arr.getName =  function(){
  return this.name
}
arr.__proto__.constructor.prototype.sayHello = function(){
  return 'hello'
}
arr.__proto__.constructor.prototype.parentName = 'say uncle'
for(let i of arr){
  console.log(i)
  // 'a', 'b', 'c'
}

遍历对象

  1. 使用for in遍历对象会遍历对象原型链的方法名和属性名,for in 循环实际是为循环可枚举(enumerable)对象而设计的
const obj = {
  name:'uncle',
  gender: 'male',
  age:12,
}
obj.hobby = 'coding'
obj.getName = function(){
  return this.name;
}
obj.__proto__.constructor.prototype.sayHello = function(){
  return "hello"
}
for(let i in obj){
  if(obj.hasOwnProperty(i)){
    console.log('ownProperty',i)
    // name, gender, age, hobby, getName
  }else{
    console.log('not ownProperty',i)
    // sayHello
  }
}

而使用 for of 遍历对象则会报错

for(let i of obj){
  console.log(i)
}
// error Uncaught TypeError: obj is not iterable

这是为什么呢?
这是因为能够被for of正常遍历的数据类型都需要实现一个遍历器Iterator。而数组、字符串、Set、Map结构,早就内置好了Iterator(迭代器),它们的原型中都有一个Symbol.iterator方法,而Object对象并没有实现这个接口,使得它无法被for of遍历。

我们可以通过为Object实现一个Iterator来使Object可以使用正常for of遍历

Object.prototype[Symbol.iterator] = function() {
  let _this = this
  let index = 0
  let length = Object.keys(_this).length
  return {
      next:() => {
          let value = _this[Object.keys(_this)[index]]
          let done = (index >= length)
          index++
          return {value,done}
      }
  }
}

for(let i of obj){
  console.log(i)
}

这样对象就可以使用for of正确遍历啦!



作者:灯下草虫鸣314
链接:https://www.jianshu.com/p/9bbf259c7c38
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted @ 2022-12-01 20:33  小饿爽  阅读(112)  评论(0编辑  收藏  举报