es6 yield表达式
yield表达式
如果在 Generator函数内部,调用另一个 Generator函数,默认情况下是没有效果的。
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
foo();
yield 'y';
}
for (let v of bar()){
console.log(v);
}
// "x"
// "y"
上面代码中,foo
和bar
都是 Generator函数,在bar
里面调用foo
,是不会有效果的。
这个就需要用到yield*
表达式,用来在一个 Generator函数里面执行另一个 Generator函数。
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
yield 'a';
yield 'b';
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
for (let v of foo()) {
yield v;
}
yield 'y';
}
for (let v of bar()){
console.log(v);
}
// "x"
// "a"
// "b"
// "y"
再来看一个对比的例子。
function* inner() {
yield 'hello!';
}
function* outer1() {
yield 'open';
yield inner();
yield 'close';
}
var gen = outer1()
gen.next().value // "open"
gen.next().value // 返回一个遍历器对象
gen.next().value // "close"
function* outer2() {
yield 'open'
yield* inner()
yield 'close'
}
var gen = outer2()
gen.next().value // "open"
gen.next().value // "hello!"
gen.next().value // "close"
上面例子中,outer2
使用了yield*
,outer1
没使用。结果就是,outer1
返回一个遍历器对象,outer2
返回该遍历器对象的内部值。
从语法角度看,如果yield
表达式后面跟的是一个遍历器对象,需要在yield
表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*
表达式。
let delegatedIterator = (function* () {
yield 'Hello!';
yield 'Bye!';
}());
let delegatingIterator = (function* () {
yield 'Greetings!';
yield* delegatedIterator;
yield 'Ok, bye.';
}());
for(let value of delegatingIterator) {
console.log(value);
}
// "Greetings!
// "Hello!"
// "Bye!"
// "Ok, bye."
上面代码中,delegatingIterator
是代理者,delegatedIterator
是被代理者。由于yield* delegatedIterator
语句得到的值,是一个遍历器,所以要用星号表示。运行结果就是使用一个遍历器,遍历了多个 Generator函数,有递归的效果。
yield*
后面的 Generator函数(没有return
语句时),等同于在 Generator函数内部,部署一个for...of
循环。
function* concat(iter1, iter2) {
yield* iter1;
yield* iter2;
}
// 等同于
function* concat(iter1, iter2) {
for (var value of iter1) {
yield value;
}
for (var value of iter2) {
yield value;
}
}
上面代码说明,yield*
后面的 Generator函数(没有return
语句时),不过是for...of
的一种简写形式,完全可以用后者替代前者。反之,在有return
语句时,则需要用var value = yield* iterator
的形式获取return
语句的值。
如果yield*
后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员。
function* gen(){
yield* ["a", "b", "c"];
}
gen().next() // { value:"a", done:false }
上面代码中,yield
命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器对象。
实际上,任何数据结构只要有 Iterator 接口,就可以被yield*
遍历。
let read = (function* () {
yield 'hello';
yield* 'hello';
})();
read.next().value // "hello"
read.next().value // "h"
上面代码中,yield
表达式返回整个字符串,yield*
语句返回单个字符。因为字符串具有 Iterator 接口,所以被yield*
遍历。
如果被代理的 Generator函数有return
语句,那么就可以向代理它的 Generator函数返回数据。
function *foo() {
yield 2;
yield 3;
return "foo";
}
function *bar() {
yield 1;
var v = yield *foo();
console.log( "v: " + v );
yield 4;
}
var it = bar();
it.next()
// {value: 1, done: false}
it.next()
// {value: 2, done: false}
it.next()
// {value: 3, done: false}
it.next();
// "v: foo"
// {value: 4, done: false}
it.next()
// {value: undefined, done: true}
上面代码在第四次调用next
方法的时候,屏幕上会有输出,这是因为函数foo
的return
语句,向函数bar
提供了返回值。
再看一个例子。
function* genFuncWithReturn() {
yield 'a';
yield 'b';
return 'The result';
}
function* logReturned(genObj) {
let result = yield* genObj;
console.log(result);
}
[...logReturned(genFuncWithReturn())]
// The result
// 值为 [ 'a', 'b' ]
上面代码中,存在两次遍历。第一次是扩展运算符遍历函数logReturned
返回的遍历器对象,第二次是yield*
语句遍历函数genFuncWithReturn
返回的遍历器对象。这两次遍历的效果是叠加的,最终表现为扩展运算符遍历函数genFuncWithReturn
返回的遍历器对象。所以,最后的数据表达式得到的值等于[ 'a', 'b' ]
。但是,函数genFuncWithReturn
的return
语句的返回值The result
,会返回给函数logReturned
内部的result
变量,因此会有终端输出。
yield*
命令可以很方便地取出嵌套数组的所有成员。
function* iterTree(tree) {
if (Array.isArray(tree)) {
for(let i=0; i < tree.length; i++) {
yield* iterTree(tree[i]);
}
} else {
yield tree;
}
}
const tree = [ 'a', ['b', 'c'], ['d', 'e'] ];
for(let x of iterTree(tree)) {
console.log(x);
}
// a
// b
// c
// d
// e
下面是一个稍微复杂的例子,使用yield*
语句遍历完全二叉树。
// 下面是二叉树的构造函数,
// 三个参数分别是左树、当前节点和右树
function Tree(left, label, right) {
this.left = left;
this.label = label;
this.right = right;
}
// 下面是中序(inorder)遍历函数。
// 由于返回的是一个遍历器,所以要用generator函数。
// 函数体内采用递归算法,所以左树和右树要用yield*遍历
function* inorder(t) {
if (t) {
yield* inorder(t.left);
yield t.label;
yield* inorder(t.right);
}
}
// 下面生成二叉树
function make(array) {
// 判断是否为叶节点
if (array.length == 1) return new Tree(null, array[0], null);
return new Tree(make(array[0]), array[1], make(array[2]));
}
let tree = make([[['a'], 'b', ['c']], 'd', [['e'], 'f', ['g']]]);
// 遍历二叉树
var result = [];
for (let node of inorder(tree)) {
result.push(node);
}
result
// ['a', 'b', 'c', 'd', 'e', 'f', 'g']
es6 yield表达式相关推荐
- python学习第十节(yield表达式的应用+内置函数)
上节复习 yield表达式 g.send(1) send函数是相当于next并且给yield传一个值,先传值,再next 加上装饰器 yield表达式的应用 第一个是当前目录的地址 第二个是当前目录下 ...
- python生成器yield原理_Python generator生成器和yield表达式详解
前言 Python生成器(generator)并不是一个晦涩难懂的概念.相比于MetaClass和Closure等概念,其较为容易理解和掌握.但相对于程序结构:顺序.循环和分支而言其又不是特别的直观. ...
- yield表达式形式的应用
基本格式 如何给yield传值 yield表达式形式的应用 栗子一吃货函数 栗子二模拟linux中的命令 grep -rl 查找内容 目录 基本格式 x = yield 把yield的接收值,赋值给x ...
- es6 Class 表达式
Class 表达式 与函数一样,ES6 类也可以使用表达式的形式定义. const MyClass = class Me { getClassName() { return Me.name; } }; ...
- ES6——generator与yield
文章目录 一.Generator生成器函数 1. 特点 2. 关联概念 二.yield的加入 1. 引入 2. yield 特点 三.举个例子 一.Generator生成器函数 它是ES6新推出的一种 ...
- Python中的yield关键字及表达式、生成器、生成器迭代器、生成器表达式详解
文章目录 1. yield关键字及表达式.生成器.生成器迭代器.生成器表达式 1.1 yield关键字及表达式(yield expression) 1.1.1 yield关键字 1.1.2 yield ...
- es6 generator_让我们探索一下ES6 Generators
es6 generator by Tiago Lopes Ferreira 由Tiago Lopes Ferreira 让我们探索一下ES6 Generators (Let's explore ES6 ...
- 【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)
一.介绍 现在的网络上已经有各样关于 ECMAScript 规范介绍和分析的文章,而我自己重新学习一遍这些规范,整理出这么一份笔记,比较精简,主要内容涵盖ES6.ES7.ES8.ES9,后续会增加面试 ...
- ES6简单总结(搭配简单的讲解和小案例)
在学习es6的过程中,为了方便自己复习,以及查看,对api做了一个极简用例介绍.如有错误多多指正. 一 let和const 1.let (1)一个大括号就是一个块级作用域,let声明的变量只在自己作用 ...
最新文章
- 问一下,线程池里面到底该设置多少个线程?
- 爬取了1W个字节跳动岗位信息,我发现了什么?
- Unity GUI(uGUI)使用心得与性能总结
- chrome扩展推荐:有我,你又省了一个ssh客户端 --- Secure Shell
- 命令行操作svn和git和git
- MapReduce的构思和框架结构
- java学习(68):局部内部类
- C/C++unlink函数的使用
- Linux多线程实践(4) --线程特定数据
- 通勤一小时,堵车半小时,AI 救救社畜
- tcpdump常用选项
- 漏洞分析C#反编译软件Reflector 11.1.0.2167(最新版)(附补丁下载)
- 小波分析工具包 matlab,matlab小波工具箱下载|
- linux 可道云_阿里云linux+kodexplorer可道云搭建私有云盘-阿里云开发者社区
- RPGViewer - 档案文件格式概述
- 第二届“马栏山”杯国际音视频算法大赛音乐节拍检测题参赛总结及分享(Rank7)
- 看图说话之二叉树的前序,中序,后序,层次遍历方式
- win10 更新之后使用win+s 或者 win+Q 出现新闻推荐和热门搜索
- 影评系统的机遇和挑战
- 【Alpha】Scrum Meeting 5
热门文章
- 常用JS正则匹配函数
- 10个有关String的面试问题
- 网络安装archlinux(2012.8.20)笔记
- Java基础-环境变量设置及Java命令行使用
- java 注销变量_[ Java学习基础 ] Java对象的创建和销毁
- 解决 clipboard.js 在ios中失效的问题
- 干货集中营 ReactiveCocoa+RXSwift+MVVM
- Linux日常运维(rsync通过服务连接,linux日志,screen)
- 【原创】Erlang 之 entop 使用问题
- Windows Mobile 6中禁用键盘或者是禁用某些按键(C#)