简单的理解:yield的表达式形式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gao_xu_520/article/details/82146284

一.说明

yield 关键字用来暂停和继续执行一个生成器函数

(1).yield的功能:
  1. 与return类似,都可以返回值,不一样在于,yield可以返回多个值而且可暂停,再次执行可继续下一步操作,return到了就停止不在继续运行。
  2.为封装好的的函数能够使用__iter__和__next__方法,
  3.遵循迭代器的取值方式 .__next__(),触发函数的执行和函数的保存都是通过yeild保存的。  

(2).yield表达式, 四种形式:

a. 不接受输入值或者输入值是None

           yield 1

   b. 接受输入值

           s = yield 1

   c. 接受输入,但不返回数据,这样默认返回None

           s = yield

   d.既不接受输入,也不返回值,默认返回None

           yield

   第一种:当函数调用到yield时,返回yield的右边经过计算的值 ,这里说计算的意思是,yield后面可以写成函数,表达式等,

   第二种:当函数调用到yield时,必须传入一个值,该值存入s中,然后返回yield后面的表达式的值并保存当前状态

   第三种:只是将数据接受进来,然后执行yield后的语句,再次执行到yield时,保存当前状态并返回,这样的用例一般是

                 只打印一些处理消息,而不需要结果的方式。

   第四种:这样的只能遍历generator内部的数据了。

二.理解与next()

1.当外部调用生成器的 next() 方法时,yield 关键字右侧的表达式才会执行。执行结果会转化为一个对象(包含两个属性, value 和 done),作为 next() 方法的返回值。对于  var foo = yield expression 语句,yield 左侧变量 foo 的值将在下一次调用 next() 方法时获得,并且等于调用时 next() 方法的参数

function* numbers() {
    console.log('function start.');
	
    var v1 = yield 0;
    console.log('v1 = ' + v1);

    var v2 = yield 1;
    console.log('v2 = ' + v2);

	var v3 = yield 4;
    console.log('v3 = ' + v3);
	
    return 10;
}

var nums = numbers();
//调用生成器函数

	// 第 1 次调用 next, v1 的值还没有返回.
		nums.next(1)

			输出:	function start.    {value: 0, done: false}


	// 第 2 次调用 next, next 参数作为上一次 yield 值返回给 v1.
		nums.next(1)
		
			输出:v1 =1	{ value: 1, done: false }


	// 第 3 次调用 next, next 参数作为上一次 yield 值返回给 v2.
		nums.next(2)
			
			输出:v2 =2	{ value: 4, done: false }

	// 第 4次调用 next, 此时 done 的值为 true, 直接返回 return 的值.
		nums.next(4)
		
			输出:v3 = 4	{ value: 10, done: true }

2.如果yield表达式后面跟的是一个遍历器对象,需要在yield表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*表达式

function* inner() {
	yield 'a';
	yield 'b';
}
function* outer1() {
	yield 'x';
	yield inner();
	yield 'y';
}
var gen = outer1()


gen.next().value // "x"
gen.next().value // 返回一个遍历器对象  inner {<suspended>}
gen.next().value // "y"
gen.next().value // undefined


function* outer2() {
	yield 'x'
	yield* inner()
	yield 'y'
}
var gen = outer2()
gen.next().value // "x"
gen.next().value // "a"
gen.next().value // "b"
gen.next().value // "y"
gen.next().value // undefined

3.如果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"

三.for...of循环
for...of循环可以自动遍历Generator函数时生成的Iterator对象,且此时不再需要调用next方法。for...of循环的基本语法是

   for (let v of foo()) {
      console.log(v);
    }

其中foo()是迭代器对象,可以把它赋值给变量,然后遍历这个变量。

把上面的例子可以修改如下:

function* inner() {
	yield 'a';
	yield 'b';
}
function* outer1() {
	yield 'x';
	yield inner();
	yield 'y';
}
console.log('yield表达式:')
for (let v of outer1()){
	console.log(v);
}
console.log('yield*表达式:')

function* outer2() {
	yield 'x'
	yield* inner()
	yield 'y'
}
for (let v of outer2()){
	console.log(v);
}

//  yield表达式:
x
inner {<suspended>}
 y
 
//yield*表达式:
x
a
b
y

猜你喜欢

转载自blog.csdn.net/gao_xu_520/article/details/82146284