1.迭代器
迭代就是反复多次的执行一段程序,常见的循环就是一种简单的迭代。
for(let i = 0 ; i < 10; i++){
console.log(i);
}
迭代器模式描述了一个方案,可以把有些结构称为 “可迭代对象(iterable)”,因为他们实现了Iterable接口,而且可以通过迭代器Iterator有序访问结构中的数据,访问数据的过程可以称之为消费(consume)。
let arr=[1,2,3];
for(const num of arr[Symbol.iterator]()){
console.log(num);
}
//1
//2
//3
for(const num of arr){
console.log(num);
}
//1
//2
//3
Symbol.iterator是ES6中新增的特性,其含义是作为实现了Iterable接口类型暴露“默认迭代器”的属性。很多内置类型都实现了Iterable接口:字符串、数组、映射、集合、argumen对象、NodeList等DOM集合类型。在确定一个类型是否可迭代,可以用以下方式判断:
let arr = [1,2,3];
if(arr[Symbol.iterator]){
console.log(true);
}else{
console.log(false);
}
//true
let num = 0;
if(num[Symbol.iterator]){
console.log(true);
}else{
console.log(false);
}
//false
迭代器是一种一次性一次性使用的对象,用于迭代与其关联的可迭代对象。迭代器API使用 next() 便利可迭代对象中的数据,每次调用 next() 都会返回 IteratorResult 对象,包含两个属性:done 和 value,是否可继续调用 next() 继续迭代,可根据 done 查看,为 true 或者 undifined 时就无法继续迭代了。
let arr = [1,2];
let iter = arr[Symbol.iterator]();
console.log(iter.next());
//{done:false,value:1}
console.log(iter.next());
//{done:true,value:2}
console.log(iter.next());
//{done:true,value:undifined}
自定义迭代器:
class Counter{
constructor(limit){
this.limit=limit;
}
[Symbol.iterator](){
let count=1,limit=this.limit;
return {
next(){
if(count <= limit){
return {done:false,value:count++};
}else{
return {done:true,value:undifined};
}
}
};
}
}
let counter = new Counter(3);
for(let i of counter){
console.log(i)
}
//1
//2
//3
提前终止迭代器:在 for-of 循环中使用 break 、 continue 、 return 、 throw 提前退出,第二种就是结构操作并未消费所有值。第二种如下所示:
class Counter{
constructor(limit){
this.limit=limit;
}
[Symbol.iterator](){
let count=1,limit=this.limit;
return {
next(){
if(count <= limit){
return {done:false,value:count++};
}else{
return {done:true,value:undifined};
}
},
return(){
console.log("Exiting early");
return {done:true};
}
};
}
}
let counter = new Counter(5);
for(let i of counter){
if(i>2){
break;
}
console.log(i)
}
//1
//2
//Exiting early
内置语言结构在发现还有更多值可以迭代时,但不会消费这些值时,会自动调用 return() 方法。
2.生成器
生成器是一个函数,这个函数块内的代码可暂停执行,暂停执行后可恢复代码继续从暂停的地方执行。函数名称前加一个 ( * ) 号 表示它是一个生成器,只要是可以定义函数的地方,都可以定义生成器。
function * generatorFn(){};
let generatorFn = function*(){};
调用生成器函数会产生一个生成器对象,生成器对象一开始处于暂停执行的状态。与迭代器相同,生成器也实现了Iterator接口,因此具有 next() 方法,调用此方法会让生成器开始或恢复执行。在生成器中,可通过关键字 yield 中断执行。
function* generatorFn() {
yield 1;
yield 2;
return 3;
}
let generatorObj = generatorFn()
console.log(generatorObj.next())
console.log(generatorObj.next())
console.log(generatorObj.next())
console.log(generatorObj.next())
//{ value: 1, done: false }
//{ value: 2, done: false }
//{ value: 3, done: true }
//{ value: undefined, done: true }