在接触到生成器之初对generator.next()和yield之间的关系是什么没有办法理解透彻,直到看到两句话:
function* helloworld() { yield 'hello' yield 'world' } const ge = helloworld() ge.next() ge.next()
'运行
Generator helloworld中通过两个yield产出了两个状态,分别是’hello’和’world’,Generator外部获取这两个状态的方式是调用ge对象的next()方法。
第一次调用next方法获取第一个状态"hello"
,第二次调用next方法获取第二个状态"world"
。
其中yield
表达式和next
方法均用来切换执行上下文,其中next方法将执行上下文从Generator函数外部切换到内部,而yield将执行上下文从Generator函数内部切换到函数外部。除了切换上下文next还将入参传入了函数内部作为yield表达式的返回值,同理,yield也将表达式的值传递给了函数外部。所以,yield是另一种形式的return,而next方法是另一种形式的函数调用。
function* helloworld() { const a = yield 1 console.log(a) yield 3 } const ge = helloworld() const val1 = ge.next() console.log(val1.value) const val3 = ge.next(2) console.log(val3.value) // 打印顺序是1 2 3
'运行
function* helloworld() { const a = yield 1 console.log(a) yield 3 } const ge = helloworld() const val1 = ge.next() console.log(val1.value) const val3 = ge.next(2) console.log(val3.value) // 打印顺序是1 2 3
'运行
在例子里可以将next()可以当做在执行函数,而yield作为return来看的就会好理解很多。
next()
从函数第一行开始执行,到 yield 1
结束执行,返回值1到函数外部。next(2)
,从第一个yield 1
处开始执行,用2
作为yield 1
的返回值,换句话说就是函数开始执行的入参,入参被const a
接收,到yield 3
返回值3
。所以说子程序(函数)就是协程的一种特例。
函数也是封装了状态,通过调用函数获取对应状态,只是这个状态只有一个,函数只能被执行一次,retrun之后无法再继续return之后的语句执行,而generator提供了继续执行中断上下文的能力也就是调用next()方法。