关于 JavaScript 中的 yield 和生成器函数,可以参考以下文档:yield - JavaScript | MDN (mozilla.org) 和 function* - JavaScript | MDN (mozilla.org) 。
其与迭代函数相关,具体见如下代码:
// 迭代函数
function foo(x=5) {
return {
next:()=>{
return { done:!x, value:x&&x-- }
}
}
}
// 用生成器函数实现
function *foo(x=5) {
while(x) yield x--
}
// 在 x=5 时,上方生成器函数即为
function *foo() {
yield 5
yield 4
yield 3
yield 2
yield 1
}
// 将上方函数作为对象 x 的迭代器符号名属性
let x = new Object
x[Symbol.iterator] = foo
// 迭代结果相同
console.log(...x) // 5 4 3 2 1
生成器函数被调用后,并不会直接执行函数体中的内容,只是生成一个暂停状态的迭代对象。调用迭代对象的 next 方法后,才开始执行函数体中的内容。在执行到 yield 时,生成器函数会暂停挂起,直到下一次调用迭代对象的 next 方法才会继续执行之后的内容。另外,yield 作为表达式时,其值为下一次调用 next 方法时传入的值。生成器函数执行的具体流程见如下代码:
// 声明一个生成器函数
function* foo() {
console.log('before yield')
yield 10
console.log('after yield')
}
// 获取迭代对象,此时没有执行 foo 函数体中的内容
let tor = foo()
// 此时 tor 状态为启动时挂起(suspendedStart)
tor // foo {<suspended>}
// 调用 next 方法后,开始执行 foo 函数体中的内容直到 yield
tor.next() // {value: 10, done: false}
// before yield // 打印信息
// 此时 tor 状态为 yield 时挂起(suspendedYield)
tor // foo {<suspended>}
// 调用 next 方法,继续 yield 之后的函数体执行
tor.next() // {value: undefined, done: true}
// after yield // 打印信息
// 没有再遇到 yield,迭代结束,此时 tor 状态为已关闭(closed)
tor // foo {<closed>}
每个函数都有自己的执行上下文。而生成器函数的执行上下文与一般函数不同,通常在执行栈外。
----- 极客时间《JavaScript 核心原理解析》学习笔记 Day 10 -----