JS的迭代器和生成器

迭代器(Iterator)

迭代器就是一种机制,一种接口,就是给各种不同的数据结构提供访问机制。一种包含数据的结构实现了迭代器接口就可以通过for…of遍历。
Iterator的遍历过程如下:

1.会创建一个指针对象,指向此数据结构的起始位置,遍历器对象本身就是一个指
针对象。
2.它就是去调用Iterator实现的next()方法,第一次调用,就把指针指向数据的
第一个成员,且返回。第二次调用就指向第二个成员,直到最后。

每次返回的是一个对象,{value:成员数据,done:布尔值},value就是该数据结构的成员数据,done是指遍历是否结束。
下面用函数模拟next方法:

{
    //函数实现一个next方法。
    function makeItrator(arr) {
        let indexnext = 0;
        return {
            next: function () {
                console.log(indexnext);//调用4次:一次输出:0 1 2 3
                return indexnext < arr.length ? { value: arr[indexnext++], dome: false } : { value: undefined, dome: true };
            }
        }
    };
    let it = makeItrator([1, 2, 3]);//这里必须用一个原始值来指向这个函数。
    console.log(makeItrator([1, 2, 3]).next == makeItrator([1, 2, 3]).next);//输出false,因为直接电用函数名,调用一次就创建一个新的函数。
    console.log(it.next == it.next);//返回true,因为it就指向一个函数makeItrator
    console.log(it.next());//第一次调用结束的时候,it保存的这个函数里面的indexnext变成了1,再下一次调用的时候,还是这个函数
    console.log(it.next());//第二次掉调用的时候,还是那个函数,但是里面的indexnext已经变成了1。
    console.log(it.next());//{ value: 3, dome: false }
    console.log(it.next());//{ value: undefined, dome: true }
}

上面就模拟了next方法,调用一次就修改indexnext这个索引,直到结束,然后返回done:true。
迭代器的用途:就是对各种包含数据的结构实现可遍历。
用一个例子:实现用for…of对普通对象的遍历,如果对象没有实现迭代器接口时不能使用for…of遍历的。(这只是举一个例子,这样做肯定没有意义的,以为for…in可实现对象的遍历。)
代码:

{
    let obj = {
        name: "Tom",
        age: 18,
        sex: "男",
        city: "成都",
        high: "180cm",
        [Symbol.iterator]() {
            let arrName = Object.keys(this);
            let that = this;
            let index = 0;
            return {
                next: function () {
                    return index < arrName.length ? { value: [arrName[index], that[arrName[index++]]], done: false } : { done: true }
                }
            }
        }
    };
    for (let i of obj) {
        console.log(i);
    }
    //输出结果:
            [ 'name', 'Tom' ]
            [ 'age', 18 ]
            [ 'sex', '男' ]
            [ 'city', '成都' ]
            [ 'high', '180cm' ]
}

[Symbol.iterator]就是一个属性,ES6中规定Iterator接口默认部署到该属性上。也可以说是该数据结构一旦有这个属性,就说明是可迭代的(但是函数中要具体实现)。
可以看出迭代器的用途就是:实现数据结构的可遍历。

生成器函数Generator

Generator就是一个普通dingy的函数,它的特征:1.function与函数名之间一个*(星号)标识。2.函数体内部使用yield语句定义不同的内部状态。
yield:函数中遇到yield,就会把紧跟yield后面的表达式进行执行再返回,下一句语句就会暂停执行,只有下一次调用的时候才会执行下一句。
例如:

{
    function* generator() {
        yield 1;
        yield 2;
        return undefined;
    };
    let ge = generator();//该函数会返回一个迭代器对象,所以就直接调用next()
    console.log(ge.next());// { value: 1, done: false }
    console.log(ge.next());// { value: 2, done: false }
    console.log(ge.next());// { value: undefined, done: true }
}

生成器和迭代器的结合使用,会使得编程变得更加的方便,简洁。
例如:

{
    let obj = {
        name: "Tom",
        age: 18,
        sex: "男",
        city: "成都",
        high: "180cm",
        [Symbol.iterator]: function* () {
            for (let i in this) {
               yield [i,this[i]]
           }
        }
    };
    // let ge = obj[Symbol.iterator]()
    for (let i of obj) {
        console.log(i);
    }
    //输出结果:
            [ 'name', 'Tom' ]
            [ 'age', 18 ]
            [ 'sex', '男' ]
            [ 'city', '成都' ]
            [ 'high', '180cm' ]
}

实例:利用类和生成器函数实现:输出小于100的斐波那契数列。

{
    class Fib {
        constructor(max) {
            this.value = max;
        };
        [Symbol.iterator] = function*() {
            let f1 = 0;
            let f2 = 1;
            while (true) {
                var curent = f1;
                yield f1
                f1 = f2;
                f2 = curent + f2;
                if (f1 > this.value) {
                    return
                }
            }
        }
    }
    let fib = new Fib(100);
    for (let i of fib) {
        console.log(i);
    }
}

打印结果:在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没有昵称...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值