es6——关于迭代器和生成器

什么是迭代器

迭代器是es6中新引入的一种遍历机制,就是从一个数据集合中按照一定的顺序,不断取出数据的过程。

迭代和循环的区别

迭代强调的是按照顺序去取数据,但是不关心取多少,不关心取到的值。循环强调的是将数据依次取出

JS中迭代器

js规定,如果一个对象具有next()方法,并且该方法能返回一个对象{value:值,done是否迭代完成},那么就认为这个对象是一个迭代器。
其中next用于得到下一个数据,返回对象中的value是下一个数据的值,done是描述迭代是否完成(false未完成,true未完成,当没有下一个值时,则返回true)。见下列具体实例,

        //定义的数据,用于迭代
        const arr = [1,2,3,4,5,6,7,8,9];
        //创建一个迭代器,用于迭代一个数组
        //具有next方法,且返回一个对象{value:'',done:''}
        const iterator ={
            i:0,   //当前数据的下标
            next(){
                let result={
                    value:arr[this.i],
                    done:this.i >=arr.length,
                }
                this.i++;
                return result
            }
        }
        //第一次迭代,返回{value:'1',done:'false'}
        let data = iterator.next();
        while(!data.done){
            //在控制台输出返回对象中value的值
            console.log(data.value);
            //进行下一次迭代
            data = iterator.next();
        }

在这里插入图片描述

可迭代的对象

在js中Array、String、Map和Set都是可迭代对象。

而在es6中规定,如果对象具有知名符号 symbol.iterator并且属性值是一个迭代器创建函数,则该对象是可以进行迭代的,也就是可迭代对象。

我们可以通过隐式原型和原型查看是否是可迭代对象,

//通过隐式原型查看
console.log(new Array().__proto__);
//通过原型查看
console.log(Array.prototype);

当打印出来的对象中有Symbol.iterator属性则表示是可迭代对象

可迭代对象的迭代过程
const items = ["zero", "one", "two"];
//通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置
const it = items[Symbol.iterator]();
//随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了 value 和 done 两个属性, value 是当前属性的值, done 用于判断是否遍历结束
it.next();
//返回{value: "zero", done: false}
it.next();
//返回{value: "one", done: false}
it.next();
//返回{value: "two", done: false}
//当 done 为 true 时则遍历结束
it.next();
//返回{value: undefined, done: true}
//迭代结束

也可以通过for - of 循环遍历可迭代对象,具体案例如下,

const items = ["zero", "one", "two"];
for (let num of nums) {
  console.log(num);
}
如何迭代一个对象

我们通过原型和隐式原型可以判断对象不是一个可迭代对象,所以可以给对象添加一个迭代器,看下例:

    let obj = {
            name: "hc",
            age: 18,
            [Symbol.iterator]() {
                const keys = Object.keys(this);
                const Values = Object.values(this);
                let i = 0;
                return {
                    next() {
                        const Name = keys[i];
                        const Vlue = Values[i]
                            // const Value = this.Name;
                        const result = {
                            value: {
                                Name,
                                Vlue,
                            },
                            done: i >= keys.length
                        }
                        i++;
                        return result
                    }
                }

            }
        };
    function test(a,b){
            console.log(a,b);
    };
    test(...obj)

这样就可以迭代一个对象了,在上述案例中我们通过展开运算符可以作用于可迭代对象,这样我们就可以将可迭代对象转化为数组。

什么是生成器

生成器就是为了更加方便的编写迭代器。生成器是一个通过 Generator来创建的对象,生成器即是一个迭代器而且同时又是一个可迭代对象。

创建一个生成器

通过*来创建一个生成器

<!-- 表示这是一个生成器函数  一定会返回一个生成器 -->
function* show(){
 console.log("第一次执行");
 yield 100000;
 console.log("第二次执行");
 yield 20;
}let arr = show();
console.log(arr.next());
console.log(arr.next());
console.log(arr.next());

//下面为执行结果
//第一次执行
//{value: 100000, done: false}
//第一次执行
//{value: 20, done: false}
//{value: undefined, done: true}

其中,yield:是一个关键字 ,他只能在生成器内部使用 表示产生一个迭代数据;所以在每次调用next方法将导致生成器运行到下一个 yield关键字位置

生成器中next()方法传入参数和无参的区别
//创建一个生成器
function* sendParameter(){
    console.log("strat");
    var x = yield '2';
    console.log("one:" + x);
    var y = yield '3';
    console.log("two:" + y);
    console.log("total:" + (x + y));
}

//next不传参
var sendp1 = sendParameter();
sendp1.next();
// strat
// {value: "2", done: false}
sendp1.next();
// one:undefined
// {value: "3", done: false}
sendp1.next();
// two:undefined
// total:NaN
// {value: undefined, done: true}


//next传参
var sendp2 = sendParameter();
sendp2.next(10);
// strat
// {value: "2", done: false}
sendp2.next(20);
// one:20
// {value: "3", done: false}
sendp2.next(30);
// two:30
// total:50
// {value: undefined, done: true}

在上述案例中,当next中传入值时,该参数会作为上一步yield的返回值,而不传入值时,yield 表达式的返回值是 undefined

生成器中return()方法传入参数和无参的区别
function* foo(){
    yield 1;
    yield 2;
    yield 3;
}
var f = foo();
f.next();
// {value: 1, done: false}
f.return("foo");
// {value: "foo", done: true}
f.next();
// {value: undefined, done: true}

在上述案例中,return 方法提供参数时,返回该参数;不提供参数时,返回 undefined .

生成器中的小细节

1.Generator 函数与普通函数的区别:一是在 function 后面,函数名之前有个*,二是函数内部有 yield 表达式。
2.生成器函数可以有返回值,返回值出现在第一次出现 done为true的时候的value属性值中。
3.在生成器内部,可以调用其他生成函数,但是注意前面要加上*号。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值