ES6笔记--迭代器&生成器

迭代器

Iterator是 ES6 引入的一种新的遍历机制,迭代器有两个核心概念:
1 迭代器是一个统一的接口,它的作用是使各种数据结构可被便捷的访问,它是通过一个键为Symbol.iterator 的方法来实现。
2 迭代器是用于遍历数据结构元素的指针(如数据库中的游标)。

迭代过程
迭代的过程如下:
通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置,随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了 value 和 done 两个属性,value 是当前属性的值, done 用于判断是否遍历结束,当 done 为 true 时则遍历结束;

const items = ["zero", "one", "two"];
const it = items[Symbol.iterator]();
it.next();
>{value: "zero", done: false}
it.next();
>{value: "one", done: false}
it.next();
>{value: "two", done: false}
it.next();
>{value: undefined, done: true}

      先创建一个数组,然后通过 Symbol.iterator 方法创建一个迭代器,之后不断的调用 next 方法对数组内部项进行访问,当属性 done 为 true 时访问结束。

       迭代器是协议(使用它们的规则)的一部分,用于迭代。该协议的一个关键特性就是它是顺序的:迭代器一次返回一个值。这意味着如果可迭代数据结构是非线性的(例如树),迭代将会使其线性化。

       创建可迭代对象 ,在ES6中,数组、Set、Map、字符串都是可迭代对象,默认情况下定义的对象(object)是不可迭代的,但是可以通过Symbol.iterator创建迭代器。

javascript
    const obj = {
      items: []
    }
    obj.items.push(1);//这样子虽然向数组添加了新元素,但是obj不可迭代
    for (let x of obj) {
      console.log(x) // _iterator[Symbol.iterator] is not a function
    }

    //接下来给obj添加一个生成器,使obj成为一个可以迭代的对象。
    const obj = {
      items: [],
      *[Symbol.iterator]() {
        for (let item of this.items) {
          yield item;
        }
      }
    }
    obj.items.push(1)
    //现在可以通过for of迭代obj了。
    for (let x of obj) {
      console.log(x)
    }

内建迭代器
数组、Set、Map都是可迭代对象,即它们内部实现了迭代器,并且提供了3种迭代器函数调用。
 1、entries() 返回迭代器**:返回键值对

javascript
    //数组
    const arr = ['a', 'b', 'c'];
    for(let v of arr.entries()) {
      console.log(v)
    }
    // [0, 'a'] [1, 'b'] [2, 'c']
    
    //Set
    const arr = new Set(['a', 'b', 'c']);
    for(let v of arr.entries()) {
      console.log(v)
    }
    // ['a', 'a'] ['b', 'b'] ['c', 'c']

    //Map
    const arr = new Map();
    arr.set('a', 'a');
    arr.set('b', 'b');
    for(let v of arr.entries()) {
      console.log(v)
    }
    // ['a', 'a'] ['b', 'b']

2、values() 返回迭代器**:返回键值对的value

javascript
    //数组
    const arr = ['a', 'b', 'c'];
    for(let v of arr.values()) {
      console.log(v)
    }
    //'a' 'b' 'c'

    //Set
    const arr = new Set(['a', 'b', 'c']);
    for(let v of arr.values()) {
      console.log(v)
    }
    // 'a' 'b' 'c'

    //Map
    const arr = new Map();
    arr.set('a', 'a');
    arr.set('b', 'b');
    for(let v of arr.values()) {
      console.log(v)
    }
    // 'a' 'b'	

3、keys() 返回迭代器**:返回键值对的key

javascript
    //数组
    const arr = ['a', 'b', 'c'];
    for(let v of arr.keys()) {
      console.log(v)
    }
    // 0 1 2
    
    //Set
    const arr = new Set(['a', 'b', 'c']);
    for(let v of arr.keys()) {
      console.log(v)
    }
    // 'a' 'b' 'c'

    //Map
    const arr = new Map();
    arr.set('a', 'a');
    arr.set('b', 'b');
    for(let v of arr.keys()) {
      console.log(v)
    }
    // 'a' 'b'	

 生成器

  它是函数:用来返回迭代器。2个关键点,一个是函数、一个是返回迭代器。是ES6中特有的,一个带有*(星号)的函数,同时你也需要使用到yield。

javascript
    //生成器函数,ES6内部实现了迭代器功能,你要做的只是使用yield来迭代输出。
    function *createIterator() {
      yield 1;
      yield 2;
      yield 3;
    }
    const a = createIterator();
    console.log(a.next()); //{value: 1, done: false}
    console.log(a.next()); //{value: 2, done: false}
    console.log(a.next()); //{value: 3, done: false}
    console.log(a.next()); //{value: undefined, done: true}

生成器的yield关键字重点就是当你执行一次next(),那么只会执行一个yield后面的内容,然后语句终止运行。

yield使用限制:yield只可以在生成器函数内部使用,如果在非生成器函数内部使用,则会报错。

javascript
    function *createIterator(items) {
        //你应该在这里使用yield
      items.map((value, key) => {
        yield value //语法错误,在map的回调函数里面使用了yield
      })
    }
    const a = createIterator([1, 2, 3]);
    console.log(a.next()); //无输出

生成器函数表达式

javascript
    const createIterator = function *() {
        yield 1;
        yield 2;
    }
    const a = createIterator();
    console.log(a.next());

在对象中添加生成器函数

javascript
    const obj = {
      a: 1,
      *createIterator() {
        yield this.a
      }
    }
    const a = obj.createIterator();
    console.log(a.next());  //{value: 1, done: false}

 

你可能感兴趣的:(前端学习)