高下相倾,前后相随——iterator 与 for ... of 循环

  iterator 是es6新提供的一种遍历器。本质上是一个接口,为各种不同的数据结构,提供统一的访问机制。

  数据只要部署了iterator接口,便是可遍历的数据,标志是具有Symbol.iterator属性。换句话说,我们只要给数据部署这个属性,就可以将数据变为可遍历的数据。具体表现是数据能否用for...of 遍历。

  原生具有iterator接口的数据类型:set, map, nodeList,string, arguments。这些数据类型是可以用for...of 遍历的。 

// 数组的Symbol.iterator
    let arr = [1,2,4,65];
    let iter = arr[Symbol.iterator]();
    console.log(iter.next())
   // 一个对象如果要具备可被for of 循环调用的Iterator接口,就必须在Symbol.iterator的属性上部署遍历器生成的方法
    class RangeIterator {
        constructor(start, stop){
            this.value = start;
            this.stop = stop;
        }
        [Symbol.iterator](){return this}
        next () {
            let value = this.value;
            if (value < this.stop) {
                this.value ++ ;
                return {done: false, value: value}
            } else {
                return {done: true, value: undefined}
            }
        }
    }
    function range(start, stop) {
       return new RangeIterator(start, stop)
    }
    for (let v of range(0, 3)) {
       // console.log(v)
    }
    
    // 遍历器实现指针结构的例子
    function obj(value) {
        this.value = value;
        this.next = null;
    }
    obj.prototype[Symbol.iterator] = function () {
        let iterator = {next: next};
        let current = this;
        function next() {
            if (current) {
                let value = current.value;
                current = current.next;
                return {done: false, value: value};
            } else {
                return {done: true}
            }
        }
        return iterator;
    }
    let one = new obj(1);
    let two = new obj(2);
    let three = new obj(3);
    one.text = two;
    two.next = three;
    for (let i of one) {
        console.log(i)
    }
    // 对于类数组的对象(存在键值名和length属性),部署iterator接口,有一个简单的方法,就是Symbol.iterator 方法直接引用数组的Iterator接口
    NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
    // 或者
    NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
    // 默认调用iterator的场合
    /*
    * 解构赋值
    * 扩展运算符
    * yield*
    * 数组的遍历会调用遍历器的接口,所以任何接受数组为参数的场合,都会调用遍历器接口
    *
    * */
    // 字符串的iterator 接口
    let str = 'adf';
    let str_iterator = str[Symbol.iterator]();
    console.log(str_iterator.next(), str_iterator.next(), str_iterator.next())

 

  

posted @ 2018-03-30 21:01  木子青牛  阅读(205)  评论(0编辑  收藏  举报