博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6中的yield
阅读量:7009 次
发布时间:2019-06-28

本文共 3195 字,大约阅读时间需要 10 分钟。

yield 关键字用来暂停和恢复一个生成器函数((function* 或遗留的生成器函数)。

语法

[rv] = yield [expression];复制代码

expression 定义通过迭代器协议从生成器函数返回的值。如果省略,则返回undefined。

rv 返回传递给生成器的next()方法的可选值,以恢复其执行。

描述

  • yield关键字使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。

  • yield关键字实际返回一个IteratorResult对象,它有两个属性,value和done。value属性是对yield表达式求值的结果,而done是false,表示生成器函数尚未完全完成。

  • 一旦遇到 yield 表达式,生成器的代码将被暂停运行,直到生成器的 next() 方法被调用。每次调用生成器的next()方法时,生成器都会恢复执行,直到达到以下某个值:

    • yield,导致生成器再次暂停并返回生成器的新值。 下一次调用next()时,在yield之后紧接着的语句继续执行。
    • throw用于从生成器中抛出异常。这让生成器完全停止执行,并在调用者中继续执行,正如通常情况下抛出异常一样。
    • 到达生成器函数的结尾;在这种情况下,生成器的执行结束,并且IteratorResult给调用者返回undefined并且done为true。
    • 到达return 语句。在这种情况下,生成器的执行结束,并将IteratorResult返回给调用者,其值是由return语句指定的,并且done 为true。
  • 如果将参数传递给生成器的next()方法,则该值将成为生成器当前yield操作返回的值。

  • 在生成器的代码路径中的yield运算符,以及通过将其传递给Generator.prototype.next()指定新的起始值的能力之间,生成器提供了强大的控制力。

说明

  • yield并不能直接生产值,而是产生一个等待输出的函数
  • 除IE外,其他所有浏览器均可兼容(包括win10 的Edge)
  • 某个函数包含了yield,意味着这个函数已经是一个Generator
  • 如果yield在其他表达式中,需要用()单独括起来
  • yield表达式本身没有返回值,或者说总是返回undefined(由next返回)
  • next()可无限调用,但既定循环完成之后总是返回undeinded

next()

  • next()可以带一个参数,该参数会被认为是上一个yield整体的返回值,稍后将在代码中展示。

  • 可以在不同阶段从外部直接向内部注入不同的值来调整函数的行为(这一点是其他循环很难做到的,或要付出较大的代价才可以做到)

简单例子

function* countAppleSales () {  var saleList = [3, 7, 5];  for (var i = 0; i < saleList.length; i++) {    yield saleList[i];  }}var appleStore = countAppleSales(); console.log(appleStore); // Generator { }console.log(appleStore.next(countAppleSales())); // { value: 3, done: false }console.log(appleStore.next()); // { value: 7, done: false }console.log(appleStore.next()); // { value: 5, done: false }console.log(appleStore.next()); // { value: undefined, done: true }复制代码

参数对比

function* countAppleSales(){    for(var i=0; true; i++){        var reset = yield i;        if(reset){            i = -1;        }    }}var appleStore = countAppleSales();console.log(appleStore.next()); //{ value: 0, done: false }console.log(appleStore.next()); //{ value: 1, done: false }console.log(appleStore.next()); //{ value: 2, done: false }console.log(appleStore.next(true)); //{ value: 0, done: false }console.log(appleStore.next()); //{ value: 1, done: false }console.log(appleStore.next()); //{ value: 2, done: false }复制代码
  1. 调用next(),会产生许多i的值, 但是不会影响reset,因为yield直接将值return出来了。
  2. 当传值true后,yield及他的参数整体变为true赋值给reset,这是reset会被执行,从而满足循环内的判断条件
  3. 不会平白增加循环的时间复杂度,因为不传参的时候,并不会占用更多的内存

深入理解

function* test(x){    var y = 2 * (yield (x + 1));    var z = yield(y/3);    console.log("x=" + x + ",y=" + y + ",z=" + z);    return (x + y + z);}var a = test(5);a.next(); //{ value: 6, done: false }a.next(); //{ value: NaN, done: false }a.next(); //x=5,y=NaN,z=undefined web-517059656c042747f821.js:1:478047          //{ value: NaN, done: true }a.next();{ value: undefined, done: true }var b = test(5);b.next(); //{ value: 6, done: false }b.next(12); //{ value: 8, done: false }b.next(13); //x=5,y=24,z=13 web-517059656c042747f821.js:1:478047            //{ value: 42, done: true }b.next(); //{ value: undefined, done: true }复制代码

A组

  1. x恒为5,所以第一次调用传空没问题,可得到对应的第一个yield返回值:yield (x + 1)
  2. 第二次调用,无参数传入,所以y为NaN(2* undefined),自然得不到z
  3. 第三次调用同上分析

B组

  1. x恒为5,所以第一次调用传空没问题,可得到对应的第一个yield返回值:yield (x + 1)
  2. 第二次调用,传入12,所以y为24(yield (x + 1)=入参),得到第二个yield: yield (y / 3)=8
  3. 第三次调用同上分析,得到最后的z值并return=42

参考文章:

转载地址:http://fbitl.baihongyu.com/

你可能感兴趣的文章
最大流EK算法
查看>>
在nuxt中引入Font Awesome字体图标库
查看>>
sql trace script
查看>>
程序员,请不要抢系统管理员的饭碗
查看>>
VCS双机由于ID冲突导致启动失败
查看>>
Windows 8上安装本地回环网卡
查看>>
修改计算机名的注意事项
查看>>
PowerBI从Exchange跟踪日志中分析数据和KPI展现
查看>>
你能成为什么样的人,取决于你心中的那颗种子!
查看>>
接口自动化测试系列之PHPUnit介绍和环境搭建
查看>>
通过ssl调用远程WebService
查看>>
SQL Server 何时将“脏页”回写到硬盘
查看>>
笔记本电脑的选购之一(2011年10月)
查看>>
电子商务时代必知的PKI及HTTPS
查看>>
程序员教你如何追女生
查看>>
各种测试用例简要模板
查看>>
SCCM 2007 R2部署、操作详解系列之概念篇一:SCCM功能详解
查看>>
Hyper-V 2016 系列教程34 在局域网内架设Windows时间服务器
查看>>
初级运维工程师面试题总结
查看>>
【COCOS2D-X 备注篇】cocos2dx 获取手机截屏等意外取消触屏事件的处理方法!
查看>>