资讯专栏INFORMATION COLUMN

切图崽的自我修养-[ES6] 迭代器Iterator浅析

happyfish / 2524人阅读

摘要:任何数据结构只要部署接口,就可以完成遍历操作即依次处理该数据结构的成员。的遍历某个数据结构过程是这样的比如对进行遍历创建一个指针对象,指向当前数组的起始位置。

Iterator

这真是毅种循环

Iterator不是array,也不是set,不是map, 它不是一个实体,而是一种访问机制,是一个用来访问某个对象的接口规范,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的成员)。

Iterator的遍历某个数据结构过程是这样的(比如对array进行遍历)

创建一个指针对象,指向当前数组的起始位置。也就是说,遍历器对象本质上,就是一个指针对象

第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员, 这时候的返回值是{value:array[0], done:false}

第二次调用指针对象的next方法,指针就指向数据结构的第二个成员,这时候的返回值是{value:array[1], done:false}

不断调用指针对象的next方法,直到它指向数据结构的结束位置这时候的返回值是{value:array[array.length-1], done:true}

遍历完毕

为数组["a","b"]手动写一个iterator接口

var itertaor = makeIterator(["a", "b"]);

iterator.next() // { value: "a", done: false }
iterator.next() // { value: "b", done: false }
iterator.next() // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}
function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

等价于:

let iterator =     
makeIterator(["a","b"])=
{next:function(){xxxx}}

等价于:

iterator.next() 
= nextIndex

所以当 var iterator = makeIterator(["a","b"])执行完,这时候makeIterator函数内部的nextIndex=0, 但由于makeIterator外部变量iterator返回了一个引用{next:function(){xxx}},所以makeIterator函数无法关闭,现在处于内存泄漏状态(函数的执行上下文环境没有关闭啊我摔!),

执行完第一个iterator.next()的时候, 由于此时nextIndex=0, nextIndex{value: array[nextIndex++], done: false},这一句实际等价于: 返回{value: array[nextIndex], done: false}然后nextIndex=nextIndex+1,现在nextIndex=1了

执行完第二个iterator.next()的时候, 由于此时nextIndex=1, nextIndex{value: array[nextIndex++], done: false},这一句实际等价于: 返回{value: array[nextIndex], done: false}然后nextIndex=nextIndex+1,现在nextIndex=2了

执行完第三个iterator.next()的时候, 由于此时nextIndex=2, nextIndex{value: undefined, done: true}

可遍历对象

事实上,我们不需要手动写array/set/map的Iterator接口了,因为ES6规定它们是可遍历对象,所以对应的Iterator接口已经被添加到对应的Symbol.iterator属性上了(所以这三种数据结构才能用keys(for..of)/values(for..of)/entries(for..of)/foreach这种方法进行遍历),你可以通过如下方式来获取

    let arr = ["a", "b", "c"];
    let arrIterator = `arr[Symbol.iterator]()`
    
    
    let set = new Set([1,2,3]);
    let setIterator = `set[Symbol.iterator]()`
    
    let map = new Map([x,1][y,2]);
    let mapIterator = `map[Symbol.iterator]()`
    
非可遍历对象

对于非可遍历对象,比如{a:1,b:2},ES6并没有规定这种对象键值对为可遍历对象,所以用for..of是不能对它进行遍历的.如果要使一个对象变成可遍历的,需要手动添加Iterator规则接口到它的Symbol.iterator属性上去,比如

    let obj = {
      data: [ "hello", "world" ],
      [Symbol.iterator]() {
        const self = this;
        let index = 0;
        return {
          next() {
            if (index < self.data.length) {
              return {
                value: self.data[index++],
                done: false
              };
            } else {
              return { value: undefined, done: true };
            }
          }
        };
      }
    };
    

对于其他的不可遍历对象(比如类数组对象),你可以手动在Symbol.iterator属性上部署上手写的Iterator接口(这样你自己可以写遍历规则),也可以让Symbol.iterator属性直接指向array的Iterator接口(这样就是用的数组的遍历规则)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80210.html

相关文章

  • 切图崽的自我修养-[ES6] 迭代Iterator浅析

    摘要:任何数据结构只要部署接口,就可以完成遍历操作即依次处理该数据结构的成员。的遍历某个数据结构过程是这样的比如对进行遍历创建一个指针对象,指向当前数组的起始位置。 Iterator 这真是毅种循环 Iterator不是array,也不是set,不是map, 它不是一个实体,而是一种访问机制,是一个用来访问某个对象的接口规范,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Ite...

    neu 评论0 收藏0
  • 切图崽的自我修养-[ES6] 迭代Iterator浅析

    摘要:任何数据结构只要部署接口,就可以完成遍历操作即依次处理该数据结构的成员。的遍历某个数据结构过程是这样的比如对进行遍历创建一个指针对象,指向当前数组的起始位置。 Iterator 这真是毅种循环 Iterator不是array,也不是set,不是map, 它不是一个实体,而是一种访问机制,是一个用来访问某个对象的接口规范,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Ite...

    springDevBird 评论0 收藏0
  • 切图崽的自我修养-[ES6] 生成Generator浅析

    摘要:搞这么神秘其实就是个迭代器的核心实际上就是一个,通过关键字能够把函数体拆成完全可控执行片段,在函数体外部通过来对这些执行片段进行遍历这和遍历这些数据结构是一个道理只不过用来遍历函数片段,而用来遍历元素对生成器执行操作,进行生成器的入口开始执 Generator 搞这么神秘 其实就是个迭代器 Generator的核心实际上就是一个Iterator,通过yield关键字能够把函数体拆成完全...

    Dogee 评论0 收藏0
  • 切图崽的自我修养-[ES6] 生成Generator浅析

    摘要:搞这么神秘其实就是个迭代器的核心实际上就是一个,通过关键字能够把函数体拆成完全可控执行片段,在函数体外部通过来对这些执行片段进行遍历这和遍历这些数据结构是一个道理只不过用来遍历函数片段,而用来遍历元素对生成器执行操作,进行生成器的入口开始执 Generator 搞这么神秘 其实就是个迭代器 Generator的核心实际上就是一个Iterator,通过yield关键字能够把函数体拆成完全...

    李义 评论0 收藏0
  • 切图崽的自我修养-[ES6] 生成Generator浅析

    摘要:搞这么神秘其实就是个迭代器的核心实际上就是一个,通过关键字能够把函数体拆成完全可控执行片段,在函数体外部通过来对这些执行片段进行遍历这和遍历这些数据结构是一个道理只不过用来遍历函数片段,而用来遍历元素对生成器执行操作,进行生成器的入口开始执 Generator 搞这么神秘 其实就是个迭代器 Generator的核心实际上就是一个Iterator,通过yield关键字能够把函数体拆成完全...

    mj 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<