for-in和for-of区别

for-in和for-of区别

先说说结论

  • for-in适合遍历对象属性,for-of适合遍历数组
  • for-in循环出的是key值,for-of循环出的是value
  • for-in可以遍历可枚举的属性,for-of遍历的是可迭代的
  • for-of不能直接遍历普通的对象,需要通过Object.keys()搭配使用

for-in循环

最早期遍历数组的方式就是一层for循环遍历数组下标:

let a=[1,2,3,4];
for(let i=0;i<a.length;i++){
	console.log(a[i]);
}

到后面ES5发布之后,又可以通过forEach来遍历数组,但是使用forEach的缺点就是不能中断

既然想到通过for来循环,就会想到for-in:

let a=[1,2,3,4];
a.name="zhangsan"
console.log(a)
for(let index in a){
	console.log(index)
}

但是这样会出现以下几个问题:

  • 赋值给index并不是一个数字,而是一个字符串
  • for-in除了遍历数组中的元素之外,还回去遍历自定义的属性,甚至数组原型链上的属性都能访问到。
  • for-in可会不会按照数组的顺序遍历数组。

for-of循环

for-of方法修复了for-in循环的缺点,并且和forEach不同的是他还能通过breakreturn终止循环,同时 除了数组之外,还支持像Set、Map、类数组对象等数据结构, 注意:for-of循环不支持普通对象,但是如果你想迭代一个对象的属性,可以使用for-in循环或者内建的Object.keys()方法

for-of循环原理

在说原理之前先说说迭代器,那什么是迭代器呢?

所谓迭代器就是一个拥有next()方法的对象,每次调用next()方法都会返回一个结果,该结果有两个属性,一个是value表示当前获取的值,第二个是done表示遍历是否结束,下面手动实现一个迭代器:

function createIterator(items){
  function addIterator(items){
    let i = 0
    let done = false
    return {  
      next() {
        done = i >= items.length
        return {
          value: items[i++],
          done
        }
      }
    }
  }
  let iterator =[];
  //给iterator添加一个Symbol.iterator属性,只有这样这种数据才是"可遍历的"。
  iterator[Symbol.iterator] = ()=> addIterator(items)
  return iterator
}

let a=[1,2,3,4];
let iter=createIterator(a)[Symbol.iterator]();
console.log(iter.next())//{ value: 1, done: false }
console.log(iter.next())//{ value: 2, done: false }
console.log(iter.next())//{ value: 3, done: false }
console.log(iter.next())//{ value: 4, done: false }
console.log(iter.next())//{ value: undefined, done: true }

这其实也就是for-of的原理,他其实帮我们做的就是获取数据的迭代器对象,然后一个一个遍历。

那这里就有一个疑问了,我们平时定义的数组没给他添加 Symbol.iterator 属性啊,其实是数组默认 部署了Symbol.iterator 属性。

下面就模拟实现下for-of:

function forOf(obj, cb) {
    let iterable, result;

    if (typeof obj[Symbol.iterator] !== "function")
        throw new TypeError(result + " is not iterable");
    if (typeof cb !== "function") throw new TypeError("cb must be callable");

    iterable = obj[Symbol.iterator]();

    result = iterable.next();
    while (!result.done) {
        cb(result.value);
        result = iterable.next();
    }
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页