Generator函数
Generator函数可以理解为一个可以暂停执行的函数, 通过调用这个函数可以返回一个遍历器对象,然后再通过这个遍历器对象再分步的执行这个Generator函数。 先看一下它的代码
function* gen(){//Generator函数
let x = 5;
x += yield 10;
console.log(x);//30
}
let g1 = gen();
console.log(g1.next());//{value:10,done:false}
console.log(g1.next(25));//{value:undefined,done:true}
最终控制台输出的是
{value:10,done:false}
30
{value:undefined,done:true}
这里简单解释一下,首先我们用function + 一个*定义了Generator函数,这是定义Generator函数的一般形式,
然后我们使用了let g1 = gen();将这个函数的遍历器对象赋值给了g1,通过调用了g1的next方法,我们才能开始执行这个函数,并让其执行到了第一个yield位置,第一个yield后面跟了个10表示返回这个10,所以控制台第一个输出为{value:10,done:false},value即我们返回的值,done代表这个函数是否已经被执行完
注意此时我们的函数停留在了第一个yield的位置x += yield 10; 此时的x并没有开始赋值,直到我们调用了第二次的next函数,g1.next(25),这里我们传了一个参数进去,这个参数可以理解为赋值给了上一次停止的yield,所以x += yield 10的yield是有值的,值为25,所以最终x的值为30,控制台输出了30,然后再输出{value:undefined,done:true},函数执行完毕。
到这里应该能大致的知道Generator函数是怎么用得了吧
yield
- 有点像return 不过它可以接受参数也可以返回值也可以暂停函数执行
- 不能在普通函数中使用yield
- yield如果放在另一个表达式中要加圆括号,简单的说就是你最好把yield和要返回的值用圆括号括起来,否则如果在其他表达式中直接使用yield会报语法错误
- 可以用作为函数参数,不用加括号
- 单独放在赋值表达式右边也不用加括号
yield*:yield后面加个星号用于遍历那些可遍历的对象比如数组,字符串或者Generator函数的遍历器等
看一段代码
function* g(){
yield "hi"
yield "sayhi"
}
function* h(){
yield "hello"
yield* g()
}
let h1 = h()
h1.next();//hello
h1.next();//hi
h1.next();//sayhi
从以上输出结果可以知道,yield*可以在Generator函数内部去遍历另一个Generator函数,效果等同于在函数内部使用for...of遍历
Iterator
Iterator是一种接口,为不同的数据结构提供统一的访问机制,只要数据结构中部署了Iterator接口,就能完成遍历操作。
当使用for..of循环遍历某种数据结构时,该循环会自动寻找Iterator接口,默认的Iterator接口放在数据结构的Symbol.iterator属性中
let obj = {
[Symbol.iterator] : function(){
return {
next:function(){
return {value:1,done:true}
}
}
}
}
上面的obj对象就是一个可遍历的对象,因为它具有Symbol.iterator属性
原生具备Iterator接口的数据结构如下:
- Array
- Map
- Set
- String
- TypedArray
- 函数的arguments对象
- Nodelist对象
let arr = [1,2,3,4]
let iter = arr[Symbol.iterator]();
iter.next();//{value:1,done:false}
iter.next();//2
iter.next();//3
iter.next();//4
想要更详细的了解Iterator可以参考阮一峰大神的文章 文章连接