ES6可迭代对象与迭代器的理解

一、本文解决的问题

ES6中新增了一个语法for...of语句,可能很多前端工程师只是看到文档或者博客上都有介绍,它可以用来遍历数组、字符串、Set集合、Map等,但是对其中原理不太清楚。本文章就是来答疑解惑的。

二、可迭代对象

如果学过python就知道,python中有可迭代对象及迭代器之分

  • 1、可迭代对象有

    • 1.Array
    • 2.String
    • 3.Map
    • 4.Set
    • 5.arguments
    • 6.NodeList
  • 2、判断一个数据是否具有可迭代能力,只有当数据具有Symbol.iterator属性的时候才可以使用for...of进行迭代

    console.log(Array.prototype.hasOwnProperty(Symbol.iterator));
    console.log(Set.prototype.hasOwnProperty(Symbol.iterator));
    
  • 3、在浏览器控制台打印信息(举例一个数组的)

    数组的迭代器

  • 4、从上图看出Array.prototype[Symbol.iterator]是一个函数,使用typeof判断数据类型(如果不可迭代的返回是undefined)

    console.log(typeof [][Symbol.iterator]);
    console.log(typeof {}[Symbol.iterator]);
    console.log(typeof new Set()[Symbol.iterator]);
    console.log(typeof ''[Symbol.iterator]);
    

三、手动模拟一个迭代器

  • 1、迭代器的方法

    const createIterator = items => {
      const keys = Object.keys(items);
      const len = keys.length;
      let pointer = 0; // 当前的指针位置
      return {
        next() {
          const done = pointer >= len;
          const value = !done ? items[keys[pointer++]] : undefined; // 如果当前指针位置小于总长度
          return {
            value,
            done
          }
        }
      }
    }
    
  • 2、测试数组

    const iterator1 = createIterator([1,2,3,4]);
    console.log(iterator1.next());
    console.log(iterator1.next());
    console.log(iterator1.next());
    console.log(iterator1.next());
    console.log(iterator1.next());
    
  • 3、测试对象

    const iterator2 = createIterator({a: 'a', b: 'b', c: 'c'})
    console.log(iterator2.next());
    console.log(iterator2.next());
    console.log(iterator2.next());
    console.log(iterator2.next());
    console.log(iterator2.next());
    

四、既然数组等具有可迭代的能力,但是我们直接使用数组.next()会报错的(用python中的说法,可迭代不代表是一个迭代器,只有迭代器才具有next()方法)

  • 1、错误信息

    可迭代对象2

  • 2、通过上面方式判断已经具有可迭代能力的数据,如果要使用next函数,必须先将可迭代对象转成换迭代器。

  • 3、可迭代对象不一定是迭代器,但是迭代器一定是可迭代对象

五、将不可迭代的数据转换可迭代数据

  • 1、尝试在对象使用for..of

    可迭代对象3

  • 2、直接修改对象原型属性

    注意一般我们开发中不会直接串改原型,方法将在另外一篇文章分享

    Object.prototype[Symbol.iterator] = function() {
      const self = this;
      const keys = Object.keys(self);
      const len = keys.length;
      let pointer = 0;
      return {
        next() {
          const done = pointer >= len;
          const value = !done ? self[keys[pointer++]]: undefined;
          return {
            done,
            value
          }
        }
      }
    }
    let obj = {name: '哈哈', gender: '男'};
    let objItem = obj[Symbol.iterator]();
    console.log('===', objItem.next());
    for (const item of obj) {
      console.log(item)
    }
    

六、关于Generator函数的介绍

  • 1、普通函数只能返回一个值

  • 2、Generator函数可以返回多个值,也可以接受外界传递的值

  • 3、generator函数

    function * generator1() {
      console.log('开始')
      yield 1;
      yield 2;
      yield 3;
      console.log('结束')
    }
    const iterator3 = generator1();
    console.log(typeof iterator3[Symbol.iterator]);
    console.log(iterator3.next())
    for (let item of iterator3) {
    	console.log(item);
    }
    

七、关于genertaor函数传递参数的理解

注意点:只要调用一次next()不管里面是否有参数都会yield一次

  • 1、具体代码

    function * generator1() {
      console.log('开始')
      let aa = yield 1;
      console.log('aa==>', aa);
      let bb = yield aa + 2;
      console.log('bb==>', bb);
      yield 3;
      console.log('结束')
    }
    const iterator3 = generator1();
    console.log(iterator3.next()); // ①
    console.log(iterator3.next(2)); // ②
    console.log(iterator3.next(10)); // ③
    console.log(iterator3.next()); // ④
    
  • 2、上面具体实现步骤(以调用的步骤为例)

    • 1.使用步骤的时候,generator函数挂起到yield 1
    • 2.使用步骤的时候,发送的值直接赋值给aa,同时是next()函数会进行下一个yield aa + 2,当时也仅仅是挂起到yield aa + 2
    • 3.使用的时候和上面一样的
  • 3、运行结果

    开始
    { value: 1, done: false }
    aa==> 2
    { value: 4, done: false }
    bb==> 10
    { value: 3, done: false }
    结束
    { value: undefined, done: true }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水痕01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值