概述

yield关键字用于并且仅限于生成器函数(generator)内部,作用是暂停(并返回)/重启(可选修改该栈环境变量)该函数栈环境。

一般语法

调用生成器函数时返回一个可迭代对象,当调用该对象的next()方法时,函数会在遇到yield关键字的位置马上返回一个IteratorResult对象,该对象格式如下:

{value: [Mixed], done: [boolean]}

yield的行为类似于return,不同的地方在于,yield返回后并不等同于该次函数调用的结束,该函数的栈环境仍然存在于内存当中(暂停),等待下一次调用到来时,代码段将会在上一次yield返回的位置继续往下执行(重启),

这样就实现了函数的暂停/重启行为。

function* foo(index) {
let a = 2;
while (index < a) {
c = yield index++;
}
} const iterator = foo(0); console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

输出:

{value: 0, done: false}
{value: 1, done: false}
{value: undefined, done: true}

可见每次调用next()都会在yield处返回该变量的结果并不再往下执行,当下次调用next()时,该函数会在上一次yield的位置继续往下执行,直到函数真正执行完毕,返回对象的done属性被赋值为true。

改变函数内部变量

yield还有另外一种能力,就是改变该函数栈内变量的值

[rv] = yield [expression];

调用next()时接受一个参数

generator.next([vaule]);

这样多次调用(除第一次)时,就会先把vaule赋值给函数内部变量rv再继续往下执行

示例:

function* foo(index) {
let a = 2;
var b;
while (index < a) {
b = yield b;
}
} const iterator = foo(0); console.log(iterator.next('a'));
console.log(iterator.next('b'));
console.log(iterator.next('c'));

输出:

{value: undefined, done: false}
{value: "b", done: false}
{value: "c", done: false}

当yield前加=号赋值给函数内部某个变量时,在第一次调用将不会给该变量赋予任何形式的值,所以在这里的第一行输出时,value等于undefined,并不是设想的被赋值为a。让next([vaule])真正起作用,是在多次调用的时候,在重启函数时,先把该函数栈内的rv变量赋值为value后再继续执行。这有点类似于Python的nex()和send(),只不过ECMA-6只用了next()来实现这种功能。

这里有一个难点,就是难以理解rv是何时改变它的值的,为了更清晰的说明这个问题,我们更改一下上面的例子,在yield前输出一下变量b

function* foo(index) {
let a = 2;
var b;
while (index < a) {
console.log(b);
b = yield b;
}
} const iterator = foo(0); console.log(iterator.next('a'));
console.log(iterator.next('b'));
console.log(iterator.next('c'));

输出:

undefined
{value: undefined, done: false}
b
{value: "b", done: false}
c
{value: "c", done: false}

可以看见,每次调用在yield <statement>执行完成后,不管接下来是任何代码,函数都会暂停,包括return yield <statement>。示例代码中第一次调用:

console.log(b);//因为b确实还没有被赋值,输出undefined还是比较容易理解的
b = yield b;//yield b返回b的值给IteratorResult对象,这时b依然是没有任何赋值的,所以也是undefined。并且执行完yield b后函数马上暂停

直到第二次调用

iterator.next('b');

这时调用函数next()传入值"b","b"被赋值到变量b,代码继续往下执行,由于是一个循环语句,于是代码又来到了

console.log(b);//此时b已经被赋了值,所以输出"b"
b = yield b;//yield b也返回b的值给IteratorResult对象,这时b依然是"b",然后马上暂停,等待下一次调用

return yield 

     有一种情况,就是该类函数如果包含return语句又会怎样呢?我们来看看MDN对这个行为的描述:

  • A return statement is reached. In this case, execution of the generator ends and an IteratorResult is returned to the caller in which the value is the value specified by the return statement and done is true.

如预料之中的一样,return会终止函数,并返回return语句的结果,放置在IteratorResult.vaule上,同时这也意味着整个迭代结束,IteratorResult.done为true.

但是,如果是return yield [statement]呢?来看看下面的例子:

function* foo(index) {
let a = 3;
while (index < a) {
return yield index++;
}
} const iterator = foo(0); console.log(iterator.next('a'));
console.log(iterator.next('b1'));
console.log(iterator.next('c'));

输出:

{value: 0, done: false}
{value: "b1", done: true}
{value: undefined, done: true}

如果结合上小段介绍,即“改变函数内部变量”,就不难理解这个例子的行为;

在第一次调用,next()返回未经递增的index,即0,并且暂停函数;

第二次调用,重启函数,把参数的值"b1"赋值给函数栈环境的变量,但是由于这里遇到的是return,所以"b1"自然而然的返回给了IteratorResult.vaule,并且结束整个迭代;

第三次调用,由于迭代已经结束,所以这里的调用已经没有任何意义;

[JavaScript]ECMA-6 yield语法的更多相关文章

  1. JavaScript学习02 基础语法

    JavaScript学习02 基础语法 JavaScript中很多基础内容和Java中大体上基本一样,所以不需要再单独重复讲了,包括: 各种算术运算符.比较运算符.逻辑运算符: if else语句.s ...

  2. JavaScript学习之路-语法

    版权声明:未经博主允许不得转载 在JavaScript中如何写语法呢?这里你可以去看一些教学文档来得快一些,这里不介绍,有点基础的也可以复习一下. //定义变量并赋值 var a; //定义变量 va ...

  3. yield 语法备忘录

    yield 语法备忘录     yield 语法备忘录 语法 .net yield 读作:“一有得” 英式发音 皮一下~ yield 关键字向编译器指示它所在的方法是迭代器块. 编译器生成一个类来实现 ...

  4. 在JavaScript中实现yield,实用简洁实现方式。

    原题还是老赵的: http://blog.zhaojie.me/2010/06/code-for-fun-iterator-generator-yield-in-javascript.html 原以为 ...

  5. JavaScript基础(一)之语法、变量、数据类型

    1.JavaScript语法 ①区分大小写 ②弱类型变量 ③每行结尾分号可有可无 ④括号用于代码块 ⑤注释有两种方式(单行和多行注释) 2.JavaScrip变量 ①用Var声明,不要初始化 ②可以在 ...

  6. (转)JavaScript二:JavaScript语言的基本语法要求

    摘自:http://blog.csdn.net/erlian1992 要学习好JavaScript,首先我们要懂JavaScript语言的一些基本语法要求: 一,区分大小写 JavaScript语言区 ...

  7. JavaScript学习笔记-基础语法、类型、变量

    基础语法.类型.变量   非数字值的判断方法:(因为Infinity和NaN他们不等于任何值,包括自身) 1.用x != x ,当x为NaN时才返回true; 2.用isNaN(x) ,当x为NaN或 ...

  8. javascript简介和基本语法

    javascript简介 1.javascript是个脚本语言,需要有宿主文件,他的宿主文件是html文件. 用法:为了保险起见一般写在</html>之后<javascript   ...

  9. 4、JavaScript进阶篇①——基础语法

    一.认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂亮的页面,但这还不够,它只是静态页面 ...

随机推荐

  1. VisualStudio2017下ASP.NET CORE的TagHelper智能提示不能使用的解决办法

    之前在VS2017RC中就发现该问题,安装了依赖,但是前段一直点不出来asp-for,后来查了发行说明, 才知道在VS2017rc中暂时无法解决,所以一直等到VS2017正式版的发布,急冲冲的装好, ...

  2. OpenStack-Nova(4)

    一. Nova概述 使用OpenStack Compute来托管和管理云计算系统.OpenStack Compute是基础架构即服务(IaaS)系统的主要部分.主要模块在Python中实现. Open ...

  3. Jekins相关笔记

    Jekins忘记密码操作 https://blog.csdn.net/intelrain/article/details/78749635 Jekins重启 https://www.cnblogs.c ...

  4. Lodop简短问答客户反馈篇 及排查步骤 及注册相关

    A.http下打印图片正常,https下打印图片是××.(有的客户端可以,有的不可以)重置ie浏览器试试.客户反馈:(和ie浏览器的设置有关)intenet选项--高级里,我调整为和能打印出图片的电脑 ...

  5. Windows平台下载、安装、配置Apache全攻略

    本文介绍了如何在windows平台进行apache服务器的下载.安装和配置过程. 1.下载 首先进入apache for windows的官方下载地址[猛戳这里],依次在下列页面进行下载操作: 我这里 ...

  6. Bugku 分析 中国菜刀

    解压之后得到了一个流量包,只有不到10KB,美滋滋 先抓重点,过滤出http,只有6条数据记录,3条post,3条response,3条post都是一样的 随便打开一条pos 是一个assert断言, ...

  7. 【坦克大战】Unity3D多人在线游戏(泰课的坦克大战--旋转的螺丝钉)

    [坦克大战]Unity3D多人在线游戏 http://www.taikr.com/my/course/937 1.NetworkManager的介绍: 说明:选择固定生成时会自动寻找有StartPos ...

  8. 题解 UVA1567 【A simple stone game】

    题目大意 一堆石子有n个,首先第一个人开始可以去1~

  9. 用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建三:配置spring并测试

    这一部分的主要目的是 配置spring-service.xml  也就是配置spring  并测试service层 是否配置成功 用IntelliJ IDEA 开发Spring+SpringMVC+M ...

  10. saltstack主机管理项目:主机管理项目需求分析(一)

    1.场景: 我现在又一台裸机要实现一下任务 2.配置管理: 1.装上nginx,mysql 2.nginx用我指定的配置文件 3.mysql用户 4.设置一个默认的数据库访问权限 5.启动mysql ...