Generator 函数是 ES6 中新增的一种特殊函数,它可以通过函数内部的 yield 语句来实现函数执行的暂停和继续。Generator 函数广泛应用于异步编程、迭代器等场景,利用它们可以更加方便地实现一些复杂的逻辑。本文将详细介绍 Generator 函数的使用方法及相关知识点,包括:
- Generator 函数的定义方法
- Generator 函数的执行方法
- Generator 函数的 yield 语句
- Generator 函数的 next() 方法
- Generator 函数的 return() 方法
- Generator 函数的 throw() 方法
- Generator 函数的应用
1. Generator 函数的定义方法
Generator 函数的定义方法与普通函数类似,只是函数名前面多了一个 *
,用来表示这是一个 Generator 函数。下面是一个最基本的 Generator 函数示例:
--------- -------------- ----- -- ----- -- ----- -- -
以上代码通过 function*
定义了一个名为 myGenerator
的 Generator 函数,其中通过 yield
关键字实现了函数执行的暂停。在使用 Generator 函数的时候,需要调用它的 next()
方法来启动函数执行。
2. Generator 函数的执行方法
Generator 函数的执行方法与普通函数有所不同,它的执行并不会立即返回结果,而是要等到调用 next()
方法时才会执行到下一个 yield
关键字处。以下是一个简单的 Generator 函数执行示例:
--------- -------------- ----- -- ----- -- ----- -- - ----- --- - -------------- ------------------------ -- ------- -- ----- ------ ------------------------ -- ------- -- ----- ------ ------------------------ -- ------- -- ----- ------ ------------------------ -- ------- ---------- ----- -----
在上面的代码中,我们先定义了一个名为 myGenerator
的 Generator 函数,然后通过 const gen = myGenerator()
创建了一个 Generator 实例,最后分别调用 gen.next()
方法来执行函数并返回结果。可以看到,每次调用 gen.next()
方法时,函数都会从上一个 yield
关键字处逐步执行到下一个 yield
关键字处,并返回一个包含 value
和 done
两个属性的对象,其中 value
为 yield
关键字后面表达式的值,done
表示当前 Generator 实例是否已经执行完毕。
需要注意的是,当 Generator 函数执行到最后一个 yield
关键字时,它会自动执行完毕,并返回一个 value
属性为 undefined
,done
属性为 true
的对象。
3. Generator 函数的 yield 语句
通过 yield
关键字,Generator 函数可以在执行过程中暂停,并返回一个值给调用者。此时函数在下次调用 next()
方法时会从上次暂停的地方继续执行,直到下一个 yield
或者函数结束。以下是一个使用 yield
关键字的 Generator 函数示例:
--------- -------------- ----- ------- - ----- -------- --------------------- -- ------- ----- ------- - ----- ------------ --------------------- -- ---------- ------ ------- - ----- --- - -------------- ------------------------ -- ------- -------- ----- ------ ------------------------------- -- ------- ------------ ----- ------ ---------------------------------- -- ------- ------- ----- -----
在上面的代码中,我们先定义了一个名为 myGenerator
的 Generator 函数,函数中定义了三个 yield
关键字,分别返回字符串 'hello'
和 'generator'
,最后一个 yield
关键字在函数结束时返回字符串 'done'
。在调用 gen.next()
方法时,第一次执行函数时并没有传入参数,此时函数执行到第一个 yield
关键字处,返回一个包含字符串 'hello'
和 done
属性为 false
的对象。接着又调用了 gen.next('world')
方法,将 'world'
作为参数传入函数,此时函数接着上一次返回的地方继续执行,并将参数值 'world'
赋值给变量 result1
,然后输出 'world'
。最后再调用 gen.next('function')
方法,同样将 'function'
作为参数传入函数,维持上次暂停的位置继续执行,并将参数值 'function'
赋值给变量 result2
,然后输出 'function'
,最终结束函数的执行并返回一个包含字符串 'done'
和 done
属性为 true
的对象。
需要注意的是,在调用 gen.next()
方法时,如果传入的参数为空或者没有传入参数,那么 yield
关键字的值默认为 undefined
。
4. Generator 函数的 next() 方法
Generator 函数的 next()
方法用于执行函数并返回结果,该方法每次调用时会将函数执行到下一个 yield
关键字处,并返回当前 yield
关键字的值。以下是一个使用 next()
方法的 Generator 函数示例:
--------- -------------- --- - - -- ------------ ----- -- ---- - - ----- --- - -------------- ------------------------ -- ------- -- ----- ------ ------------------------ -- ------- -- ----- ------ ------------------------ -- ------- -- ----- ------
在上面的代码中,我们定义了一个名为 myGenerator
的 Generator 函数,该函数会无限循环并不断返回变量 i
的值,并且每次返回后都会将 i
自增。在调用 gen.next()
方法时,该函数会从第一次执行开始,返回一个包含变量 i
属性值的对象,接着不断执行并返回结果,直到该函数自行结束。
5. Generator 函数的 return() 方法
Generator 函数的 return()
方法用于结束函数的执行,并返回一个指定的结果。当调用该方法时,Generator 函数会从当前执行位置跳出,并返回一个包含指定结果的对象,同时将 done
属性设为 true
。以下是一个使用 return()
方法的 Generator 函数示例:
--------- -------------- --- - - -- ------------ ----- -- ---- - - ----- --- - -------------- ------------------------ -- ------- -- ----- ------ -------------------------------- -- ------- ------- ----- ----- ------------------------ -- ------- ---------- ----- -----
在上面的代码中,我们仍然是定义了一个名为 myGenerator
的 Generator 函数,并通过 const gen = myGenerator()
创建了一个 Generator 实例。接着,调用 gen.next()
方法时,该函数会从第一次执行开始,返回一个包含变量 i
属性值的对象,然后接着执行并返回结果,直到调用 gen.return('done')
方法结束函数执行并返回指定结果。最后再次调用 gen.next()
方法时会发现函数已经结束,并返回一个值为 undefined
的对象,done
属性为 true
。
6. Generator 函数的 throw() 方法
Generator 函数的 throw()
方法用于在函数执行过程中抛出一个异常,并将函数执行导向异常处理代码。当调用该方法时,Generator 函数会执行 try...catch...finally
语句,并在 catch
语句中捕获到抛出的异常。以下是一个使用 throw()
方法的 Generator 函数示例:
--------- -------------- --- - --- - - -- ------------ ----- -- ---- - - ----- --- - --------------- - - ----- --- - -------------- ------------------------ -- ------- -- ----- ------ -------------------------------- -- ------- ------------------------ -- ------- ---------- ----- -----
在上面的代码中,我们仍然是定义了一个名为 myGenerator
的 Generator 函数,并通过 const gen = myGenerator()
创建了一个 Generator 实例。在调用 gen.next()
方法时,该函数会从第一次执行开始,返回一个包含变量 i
属性值的对象,然后接着执行,并返回结果。在调用 gen.throw('error')
方法时,函数会采取异常处理逻辑,转到 catch
语句中,并输出参数值 'error'
,最后调用 gen.next()
方法时发现函数已经结束,并返回一个值为 undefined
的对象,done
属性为 true
。
7. Generator 函数的应用
7.1 实现异步逐步执行
在普通函数中,我们可以通过回调函数来实现异步逐步执行的效果,在 Generator 函数中,我们可以通过 yield
关键字来实现相同的效果。以下是一个通过 Generator 函数实现异步逐步执行的示例:
--------- -------------- ----------------- ---- ------ ----------------- ---- ------ ----------------- ---- ------ ------- - ----- --- - -------------- ----------- -- ---- - ------------- -- ----------- ------ -- ---- -
在上面的代码中,我们定义了一个名为 myGenerator
的 Generator 函数,通过 yield
关键字来实现异步逐步执行。在 myGenerator
函数中,我们输出 'step 1'
后利用 yield
关键字将函数执行暂停,等待下一次 next()
方法的调用。接着通过 setTimeout()
方法在两秒后再次调用 next()
方法,此时函数会接着上一次暂停的地方执行,并输出 'step 2'
。由于没有再次调用 next()
方法,函数最终执行结束。
7.2 实现迭代器
在 ES6 中,通过 Symbol.iterator
属性可以实现一个可迭代对象,而 Generator 函数则可以方便地实现迭代器。以下是一个使用 Generator 函数实现迭代器的示例:
--------- ------------- --- - - -- ------- - --- ----- -- ---- - - ----- -- - ------------- --- ------ ---- -- ---- ------------------ -- -- -- - -
在上面的代码中,我们通过 function*
定义了一个名为 myIterator
的 Generator 函数,其中循环三次并返回变量 i
的值。接着通过 const it = myIterator()
创建一个 Generator 实例,并利用 for...of...
语句遍历该实例,输出每次迭代后的值。
结论
Generator 函数是 ES6 中非常重要的特性之一,通过它可以方便地实现异步编程、迭代器等功能。在编写代码时,需要注意函数执行的暂停和继续关系以及返回结果的数据类型等问题,以便更好地利用 Generator 函数的特殊性质。
来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/671c70119babaf620fb0c7ed