美文网首页前端笔记
Iterator(迭代器)(数组、对象、Map、Set、Stri

Iterator(迭代器)(数组、对象、Map、Set、Stri

作者: 好奇男孩 | 来源:发表于2018-05-15 18:45 被阅读1次

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

    iterator 的作用有三个:

    • 一是为各种数据结构,提供一个统一的、简便的访问接口;

    • 二是使得数据结构的成员能够按某种次序排列;

    • 三遍历命令for...of循环

    Iterator 的遍历过程

    • (1)创建一个指针对象,指向当前数据结构的起始位置。

    • (2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。

    • (3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。

    • (4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。

    var it = makeIterator(['a', 'b']);
    
    it.next() // { value: "a" }
    it.next() // { value: "b"}
    it.next() // {  done: true }
    
    function makeIterator(array) {
      var nextIndex = 0;
      return {
        next: function() {
          return nextIndex < array.length ?
            {value: array[nextIndex++]} :
            {done: true};
        }
      };
    }
    
    let myIterable = {
      [Symbol.iterator]: function* () {
        yield 1;
        yield 2;
        yield 3;
      }
    }
    [...myIterable] // [1, 2, 3]
    

    默认 Iterator 接口

    原生具备 Iterator 接口的数据结构如下,即具有Symbol.iterator属性;

    • Array
    • Map
    • Set
    • String
    • TypedArray
    • 函数的 arguments 对象
    • NodeList 对象
    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 }
    

    有了遍历器接口,数据结构就可以用for...of循环遍历(详见下文),也可以使用while循环遍历。

    调用 Iterator 接口的场合

    一些场合会默认调用 Iterator 接口(即Symbol.iterator方法)

    解构赋值

    对数组和 Set 结构进行解构赋值时,会默认调用Symbol.iterator方法。

    let set = new Set().add('a').add('b').add('c');
    
    let [x,y] = set;
    // x='a'; y='b'
    
    let [first, ...rest] = set;
    // first='a'; rest=['b','c'];
    

    扩展运算符

    扩展运算符(...)也会调用默认的 Iterator 接口

    var str = 'hello';
    [...str] //  ['h','e','l','l','o']
    let arr = ['b', 'c'];
    ['a', ...arr, 'd']
    // ['a', 'b', 'c', 'd']
    

    只要某个数据结构部署了 Iterator 接口,就可以对它使用扩展运算符,将其转为数组

    let arr = [...iterable];
    

    yield*

    yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口

    let generator = function* () {
      yield 1;
      yield* [2,3,4];
      yield 5;
    };
    
    var iterator = generator();
    
    iterator.next() // { value: 1, done: false }
    iterator.next() // { value: 2, done: false }
    iterator.next() // { value: 3, done: false }
    iterator.next() // { value: 4, done: false }
    iterator.next() // { value: 5, done: false }
    iterator.next() // { value: undefined, done: true }
    

    其他

    数组的遍历会调用遍历器接口,任何接受数组作为参数的场合,其实都调用了遍历器接口。

    字符串的 Iterator 接口

    var someString = "hi";
    typeof someString[Symbol.iterator]
    // "function"
    
    var iterator = someString[Symbol.iterator]();
    
    iterator.next()  // { value: "h", done: false }
    iterator.next()  // { value: "i", done: false }
    iterator.next()  // { value: undefined, done: true }
    

    用Generator 函数 实现Iterator 接口

    let myIterable = {
      [Symbol.iterator]: function* () {
        yield 1;
        yield 2;
        yield 3;
      }
    }
    [...myIterable] // [1, 2, 3]
    

    任意一个对象的Symbol.iterator方法,等于该对象的迭代器生成函数,调用该函数会返回该对象的一个迭代器对象。

    相关文章

      网友评论

        本文标题:Iterator(迭代器)(数组、对象、Map、Set、Stri

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