es6——关于迭代器和生成器
什么是迭代器
迭代器是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();
}
可迭代的对象
在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.在生成器内部,可以调用其他生成函数,但是注意前面要加上*号。
上一篇: ES6 生成器函数
下一篇: 六一 | 如何用Python制作童年游戏