欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

理解可迭代对象:特性和实现方法

最编程 2024-01-13 21:02:00
...

可迭代对象可通过 for...of进行循环。

迭代器的模拟

  模拟迭代器:

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

    var it = makeIterator(['a', 'b', 1, 6, NaN, null, undefined]);
    var res;
    do {
        res = it.next();
        console.info(res.value);
    } while (!res.done);

为了实现可迭代,一个对象必须实现 iterator 方法,这意味着这个对象(或其原型链中的一个对象)必须具有带 Symbol.iterator 键的属性

检测可迭代对象

  判断当前对象是否为可迭代对象,检测该对象是否具备 Symbol.iterator 属性。

    // 以数组为例
    Array.prototype.hasOwnProperty(Symbol.iterator); // => true

  可通过检测当前对象是否具有Symbol.iterator属性来判断当前对象是否为可迭代对象。Symbol.iterator 是一个函数,所以通过typeof来检测返回值,如果返回值为'function'则为可迭代对象,如果返回值为'undefined'则为不可迭代对象。

    typeof [][Symbol.iterator]; // => 'function'
    typeof {}[Symbol.iterator]; // => 'undefined'
    typeof new Set()[Symbol.iterator]; // => 'function'
    typeof new Map()[Symbol.iterator]; // => 'function'
    typeof ''[Symbol.iterator]; // => 'function'
    var list = document.querySelectorAll('p'); // 获取dom节点
    typeof list[Symbol.iterator]; // => 'function'
    typeof new Int8Array()[Symbol.iterator]  // => 'function'
    (function(){
        typeof arguments[Symbol.iterator]; // => 'function'
    })();

原生可迭代对象

  原生具备 Iterator 接口的数据结构如下。

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的 arguments 对象
  • NodeList 对象

Symbol.iterator 为每一个对象定义了默认的迭代器,迭代器是一个对象,它提供了一个next()方法,用来返回序列中的下一项。数组如何使用.next() 方法:

    var arr = [1,2,3];
    var si = arr[Symbol.iterator]();
    si.next(); //=> {value: 1, done: false}
    si.next(); //=> {value: 2, done: false}
    si.next(); //=> {value: 3, done: false}
    si.next(); //=> {value: undefined, done: true}

可迭代对象的实现

  如何实现一个自定义的可迭代对象:

    var myIterator = {};
    myIterator[Symbol.iterator] = function* () {
        yield 'Bryan';
        yield 'programmer';
        yield 'bachelordom';
    }
    for (let val of myIterator) {
        console.info(val);
    }
    // Bryan
    // programmer
    // bachelordom
    var myIterator = {
        name: 'Bryan',
        job: 'programmer',
        condition:'bachelordom',
        *[Symbol.iterator](){
            const self = this;
            const keys = Object.keys(self);
            for(let i=0,l=keys.length;i<l;i++){
                yield self[keys[i]];
            }
        }
    };

    for (let val of myIterator) {
        console.info(val);
    }
    // Bryan
    // programmer
    // bachelordom

总结

可迭代对象的特点:

  • 可使用 for...of 进行循环;
  • 对象或者原型链当中具有 Symbol.interator 属性;
  • 可通过迭代器访问并跟踪该序列中的当前位置。(迭代器提供next()方法,返回对象包含done和value方法)

参考资料 《ECMAScript 6 入门》Iterator 和 for...of 循环 《MDN》迭代器和生成器 《MDN》Symbol.iterator

推荐阅读