简单理解一下for in 和 for of的区别

for of 不能直接循环对象

这个是为什么呢 , for of 是ES6新增的 , es6引入了Iterator的概念。只有提供了Iterator接口的数据类型才能用。Array、Set、Map等这些都有这个方法

 所以如果我们想要用for of来进行对象的遍历我们也必须为对象增加一个interator接口

这里我们用到了一个yield , 这个是interator接口的一个方法, 这是官方的描述, 这个方法具体没有去研究 , 抽时间会去看一下这个到底是什么情况

yield关键字使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。

yield关键字实际返回一个IteratorResult对象,它有两个属性,valuedonevalue属性是对yield表达式求值的结果,而donefalse,表示生成器函数尚未完全完成。

一旦遇到 yield 表达式,生成器的代码将被暂停运行,直到生成器的 next() 方法被调用。每次调用生成器的next()方法时,生成器都会恢复执行,直到达到以下某个值:

  • yield,导致生成器再次暂停并返回生成器的新值。 下一次调用next()时,在yield之后紧接着的语句继续执行。
  • throw用于从生成器中抛出异常。这让生成器完全停止执行,并在调用者中继续执行,正如通常情况下抛出异常一样。
  • 到达生成器函数的结尾;在这种情况下,生成器的执行结束,并且IteratorResult给调用者返回undefined并且donetrue
  • 到达return 语句。在这种情况下,生成器的执行结束,并将IteratorResult返回给调用者,其值是由return语句指定的,并且done 为true

如果将参数传递给生成器的next()方法,则该值将成为生成器当前yield操作返回的值。

在生成器的代码路径中的yield运算符,以及通过将其传递给Generator.prototype.next()指定新的起始值的能力之间,生成器提供了强大的控制力。

Object.prototype[Symbol.iterator]= function* (){
        let keys = Object.keys(this);
        for(let i = 0, l = keys.length; i < l; i++){
            yield this[keys[i]];
        }
    }

  我们为在Object的原型上为他添加了iterator的接口以后我们就能直接使用for of来循环对象了 , 不过好像没啥实际意义哈

另外 iterator 这个接口我们还可以这么来写 , 这东西和java的迭代器很像。

let iterator = function(){
        let i = 0 , that = this , keys = Object.keys( that );
        return {
            next(){
                if( i < keys.length ){
                    return {
                        value: that[keys[i++]] , done: false
                    };
                }
                else{
                    return {
                        value: undefined , done: true
                    }
                }
            }
        };
    };

2 原型链上的属性 for of 不会循环

3 for in 遍历时候参数是下标或者键名 是String类型 , 下标也给你转成String了 , for of 不会,是什么就是什么 , 所以这个在遍历map的时候就非常方便了,当然我们也是能拿到下标的,就解构赋值就行

for(let [key,value] of arr.entries()){
      console.log(key)
      console.log(value)
    }
原文地址:https://www.cnblogs.com/sunjinggege/p/15190989.html