欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-13 08:41:54
...

什么是迭代器

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

迭代和循环的区别

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

JS中迭代器

js规定,如果一个对象具有next()方法,并且该方法能返回一个对象{value:值,done是否迭代完成},那么就认为这个对象是一个迭代器。
其中next用于得到下一个数据,返回对象中的value是下一个数据的值,done是描述迭代是否完成(false为为完成,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();
        }

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

可迭代的对象

在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 关键字位置

生成器中text()方法传入参数和无参的区别

//创建一个生成器
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}

在上述案例中,当text中传入值时,该参数会作为上一步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.在生成器内部,可以调用其他生成函数,但是注意前面要加上*号。

相关标签: javascript es6