这是我参与更文挑战的第1天,活动详情查看: 更文挑战
(一)迭代器
Iterator迭代器就是一个接口方法,它为不同的数据结构提供了一个统一的访问机制;使得数据结构的成员能够按某种次序排列,并逐个被访问。
那么在日常开发中,如何让一个对象成为一个可迭代对象呢?即支持迭代器规范的对象(iterable)
可以给obj 对象添加Symbol.iterator属性,同时在返回的next方法中,添加value和done两个属性。
let obj = {
0:'d',
1:'dp',
2:'f',
length:4,
[Symbol.iterator]: function(){
let index = 0;
let next = () => {
return {
value:this[index],
done: this.length == ++index
}
}
return {next}
}
}
console.log([...obj])
复制代码
输出结果
value属性返回当前位置的成员,done属性是一个布尔值,表示遍历是否结束,即是否还有必要再一次调用next方法;当done为true时,即遍历完成。既让它成为了一个可迭代对象可以使用扩展运算符。
(二)生成器
生成器是一个极为灵活的结构,拥有在一个函数内暂停和恢复代码执行的能力。
其实Generator函数就是一个普通函数,但是有两个特征,一是,function关键字与函数名之间有一个星号*;二是,函数内部使用yield表达式,定义不同的内部状态。
生成器函数的使用
function* generatorFn(){}
const generatorObject = generatorFn()
console.log(generatorObject ) //generatorFn(<suspended>)
console.log(generatorObject.next())// { value: undefined, done: true }
复制代码
next()方法的返回值类似于迭代器,有一个done属性和一个value属性。函数体为空的生成器函数中间不会停留,调用一次next()就会让生成器到达done:true状态。
value 属性是生成器函数的返回值,默认undefined,可以通过生成器函数的返回值指定:
function* generatorFn(){
return 'foo'
}
const generatorObject = generatorFn()
console.log(generatorObject ) //generatorFn(<suspended>)
console.log(generatorObject.next())// { value: 'foo', done: true }
复制代码
通过yiled中断执行
yiled 关键字可以让生成器停止和开始执行,也是生成器最有用的地方。生成器函数在遇到yield关键字之前会正常执行,遇到这个关键字之后会停止执行,函数作用域的状态会被保留。停止执行的生成器函数只能通过在生成器对象上调用next()方法来恢复执行。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
复制代码
调用生成器函数会产生一个生成器对象。生成器对象一开始处于暂停执行(suspended)的状态。与迭代器相似,生成器对象也实现了iterator接口,因此具有next()方法。调用这个方法会让生成器恢复执行。
生成器对象作为可迭代对象
在生成器对象上显式调用next()方法的用处并不大。其实,如果把生成器对象当作可迭代对象,那么使用起来会很方便:
function* generatorFn(){
yiled 1;
yiled 2;
yiled 3;
}
for(const x of generatorFn()){
console.log(x)
}
//1
//2
//3
复制代码