美文网首页WEB前端程序开发让前端飞
for in与for of及遍历器Iterator

for in与for of及遍历器Iterator

作者: ascend13 | 来源:发表于2017-08-30 21:31 被阅读0次

    for in

    for in可以用来遍历对象的可枚举属性列表(包括[[prototype]]链),单独使用in操作符会检查属性是否在对象及其[[prototype]]原型链中(无论是否可以枚举)

    var obj = {
      a: 2
    }
    console.log("a" in obj);//true
    

    但是使用for in循环输出的属性名的顺序是不可预测的,返回的先后次序因浏览器而异。

    使用for in也可以遍历数组,属性为数组的索引,但是会有以下问题:

    • index索引为字符串型数字,不能直接进行几何运算
    • 遍历顺序有可能不是按照实际数组的内部顺序
    • 使用for in会遍历数组所有的可枚举属性,包括原型。例如例子中的原型方法method和name属性
    Alt text

    因此for in更适合用来遍历对象

    for of

    前面说了for in遍历的是key(键名),使用ES6的for of可以遍历数组的value(键值),mdn上对于for of的说明

    for...of语句在可迭代对象(包括 Array, Map, Set, String, TypedArray,arguments 对象等等)上创建一个迭代循环,对每个不同属性的属性值,调用一个自定义的有执行语句的迭代挂钩

    var arr = [ 1, 2, 3];
    for (var v of arr) {
      console.log( v );
    }
    // 1
    // 2
    // 3
    

    for of循环不仅支持数组,实际上述定义的可迭代对象,可迭代对象指的是具备Iterator接口的数据结构

    Iterator

    实际上for of遍历就是基于Iterator,当使用for of循环遍历某种数据结构时,该循环会自动去寻找Iterator接口

    遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

    Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。

    ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator,它是一个表达式,返回Symbol对象的iterator属性

    原生具备Iterator接口的数据结构如下

    • Array
    • Map
    • Set
    • String
    • TypedArray
    • 函数的arguments对象
    • NodeList对象

    for of循环首先会向北访问对象请求一个迭代器对象,然后通过调用迭代器对象的next()方法来遍历所有返回值

    let arr = ['a', 'b', 'c'];
    let iter = arr[Symbol.iterator]();
    
    iter.next() // { value: 'a', done: false }
    iter.next() // { value: 'b', done: false }
    iter.next() // { value: 'c', done: false }
    iter.next() // { value: undefined, done: true }
    

    上面代码中,变量arr是一个数组,原生就具有遍历器接口,部署在arr的Symbol.iterator属性上面。所以,调用这个属性,就得到遍历器对象。value是当前的遍历值,done是一个布尔值,表示是否还有可以遍历的值,这里遍历到第三个时,已经没有可以遍历的值了,但是done仍然是false,下一个才是true,这个机制和ES6中发生器函数的语义相关,这里不做讨论。

    普通的对象没有内置的Iterator接口,无法用for of遍历,但是我们可以用Symbol.iterator来自己完成对对象的遍历

    var myObject = {
      a: 2,
      b: 3,
      c: 4
    };
    
    Object.defineProperty( myObject, Symbol.iterator, {
      enumerable: false,
      writeable: false,
      configurable: true,
      value: function() {
        var o = this;
        var idx = 0;
        var ks = Object.keys( o );
        return {
          next: function() {
            return {
              value: o[ks[idx++]],
              done: (idx > ks.length)
            };
          }
        };
      }
    });
    
    var it = myObject[Symbol.iterator]();
    it.next(); //{ value: 2, done:false}
    it.next(); //{ value: 3, done:false}
    it.next(); //{ value: 4, done:false}
    it.next(); //{ value: undefined, done:true}
    
    for (var v of myObject) {
      console.log( v );
    }
    // 2
    // 3
    // 4
    

    原文地址

    相关文章

      网友评论

        本文标题:for in与for of及遍历器Iterator

        本文链接:https://www.haomeiwen.com/subject/uttfjxtx.html