当前位置 博文首页 > 纸飞机博客:iterator迭代器

    纸飞机博客:iterator迭代器

    作者:[db:作者] 时间:2021-09-07 10:06

    1、什么是迭代器(iterator)

    迭代器是一种特殊对象,是为各数据结构的迭代过程设计的专有接口。迭代器对象都有一个next。方法,每一次调用next方法 , 都会返回数据结构的当前成员的信息,即返回一个对象:

    {done: Boolean, value: any}

    value:当前成员的值。

    done:布尔值,表示遍历是否结束。

    这样不断调用next方法,直到遍历结束。

    //用ES5创建一个迭代器:
    function createlterator(arr){
        var i = 0;
        return {
            next: function(){
                var done = (i >= arr.length);
                var value = !done? arr[i++]:undefined;
                return {
                    done: done,
                    value: value
                }
             }
        }
    }
    var iterator = createlterator([1,2,3]);
    console.log(iterator.next());
    //{done: false, value: 1}
    console.log(iterator.next());
    // {done: false, value: 2}
    console.log(iterator.next());
    //{done: false, value: 3}
    console.log(iterator.next());
    //{done: true, value: undefined}

    上述ES5的例子较复杂,ES6引入了生成器 Generator,它是一种以更简单的方式创建迭代器的函数。该函数通过function后的星号"*"表示,使用内部专用关键字yield作为暂停标识,yield后表达式的值即为迭代器next。返回值中的value值。

    //用ES6生成器创建一个迭代器:
    function *createlterator(arr){
        for (let i=O;i<arr.length;i++){
            yield arr[i];
        }
    }
    let iterator = createlterator([1,2,3]);
    console.log(iterator.next());
    // {done: false, value: 1}
    console.log(iterator.next());
    // {done: false, value: 2}
    console.log(iterator.next());
    //{done: false, value: 3}
    console.log(iterator.next());
    //{done: true, value: undefined}

    当我们调用Generator函数时,并不会执行该函数,而是返回一个迭代器。

    当该迭代器调用next方法时,就会开始执行函数,在执行完第一句yield语句后自动暂停,并将yield
    后的表达式的值作为其返回值的value。

    当再次调用next方法时才会从上次停止的地方(yield [表达式]处的后面)开始继续执行,直到执行
    完下一句yield语句。?

    2、什么是可迭代对象(iterator)

    如果对象含有Symbol.iterator属性,就认为是可迭代的。Symbol.iterator本身是一 个函数,即当前数据结构的迭代器生成函数(生成器或es5函数),可以返回一个作用于附属对象的迭代器 。 常见 的Array, Map, Set, String, arguments 等都是原生可迭代对象 , 具有内置的Symbol.iterator属性(生成器),ES6的for-of需要用到可迭代对象的该属性。

    3、for-of循环机制

    可迭代对象可以使用一些ES6方法,例如 for..of语句和扩展运算符(…)。for-of在可迭代对象上创建一个迭代循环,并为每个不同属性的值执行语句。其原理是首先会调用[Symbol.iterator]。方法,返回一个迭代器对象,内含next。方法,然后重复调用 next。方法,循环一次就调用一次并得到返回值中的value。

    4、访问迭代器

    //通过Symbol.iterator。来访问可迭代对象的迭代器
    let items = [1,2,3];
    let iterator = items[Symbol.iterator]();
    console.log(iterator.next());
    // {done: false, value: 1}
    console.log(iterator.next());
    // {done: false, value: 2}
    console.log(iterator.next());
    // {done: false, value: 3}
    console.log(iterator.next());
    //{done: true, value: undefined}

    5、普通对象变可迭代对象

    一般开发中定义的对象都是不可迭代对象 ,不能使用 for - of ( 会报错 : xx is not iterable)。但如果给对象部署 Symbol.iterator属性,添加一个生成器 (es5传统生成函数也可以,但用生成器是 主流),可以使其变为可迭代对象。

    let obj = {
        "0":"aa",
        "1":"bb",
        "2":"cc"
    }
    obj[ Symbol.iterator ] = function *(){
        for(let key in this){
            let val = this[key];
            yield val;
        }
    }
    for(let i of obj){
        console.log(i)
    }
    //aa
    //bb
    //cc 

    6、总结

    迭代器:一种可以调用内部next方法进行 手动迭代的对象。

    生成器:一种用来创建迭代器的函数。

    可迭代对象:一种具有Symbol.iterator属性或称iterator接口的能被for of语句自动迭代的对象。Symbol.iterator属性对应着一个迭代器生成函数。

    另外:通过生成器(*)返回的迭代器同时也是可迭代对象 。 因为生成器会默认为其添加 Symbol.iterator属性,会返回该迭代器本身。这样可以让一个迭代器也能被可迭代对象的语法(for of或展开符…)所应用。如果是用es5函数创建的迭代器 , 返回时一般会自主添加 [Symbol.iterator]: function(){ return this },使其也成为可迭代对象。?

    cs