我是靠谱客的博主 调皮蚂蚁,最近开发中收集的这篇文章主要介绍JS Generator function* 生成器函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

生成器函数在执行时能暂停,后面又能从暂停处继续执行。调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的 迭代器 ( iterator )对象。当这个迭代器的 next() 方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield的位置为止,yield 后紧跟迭代器要返回的值。或者如果用的是yield*(多了个星号),则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。

1.生成器函数执行时是可暂停的,之后又能从暂停处继续执行。(暂停标识:yield

2.调用生成器函数返回的是一个迭代器(而不是函数内return的值,return 是函数结束标识也是生成器函数最后一个返回值)

3.yield(中译:产出)后面跟的是迭代器的返回值yeild表达式自身是没有返回值的,或者说是undefinedyield相当于一个标识符,next()执行后返回的对象的value属性的值就是yield后面表达式的生成的值)

4.生成器函数执行后返回的迭代器首次使用next()方法,会执行到第一个yield的位置,并放回该yield后紧跟着的表达式的值。

5.假如生成器函数中没有yield关键字,该函数就变成了一个暂缓执行函数,具体表现为执行生成器函数不会执行函数内的代码,只有调用生成的迭代器的next()后,函数内的代码才会执行。

6.next()返回一个对象,表示当前成员的信息,这个对象包含两个属性:valuedonevalue 属性表示本次 yield 后面表达式的生成的值,done 属性为布尔类型,表示生成器后续是否还有 yield 语句,即生成器函数是否已经执行完毕并返回。

7.yield关键字只能用在生成器函数中。function* f(){function foo(){yield 1;}}这样会报错。

生成器函数外在特征:function与函数名间有一个*,对间隔没有要求,都可以编译通过。推荐写法:function* f(){}

基础

生成器函数

function* g(x,y,z){
	let k=x+y;
	console.log('pass');
	yield k;
	yield z;
	return k+z;
}
let it=g(...[1,2,4])
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

在这里插入图片描述
在这里插入图片描述

暂缓执行函数(没有yield的生成器函数)

function *g(){
	console.log('直接执行生成器函数我是不会被打印出来的');
}
let it=g();

//试下把下面一句的注释解开
//it.next();

不会打印!解开注释后才打印

next()传参

yield表达式本身没有返回值,或者说总是返回undefined

function* g(x){
	let a=yield x;
	console.log(a);
}
let it=g(5);
console.log(it.next());
console.log(it.next());

在这里插入图片描述

next()可以带一个参数,该参数就会被当作上一个yield表达式的返回值。因此第一次使用next()时,传递参数是无效的。

function* g(x){
	let y=2+(yield x);
	let z=x+(yield y+2)
	return z;
}
let it=g(5);
console.log(it.next());//{value: 5, done: false}
console.log(it.next());//{value: NaN, done: false}
console.log(it.next());//{value: NaN, done: true}

let it2=g(5);
console.log(it2.next());//{value: 5, done: false}
console.log(it2.next(2));//{value: 6, done: false}
console.log(it2.next(2));//{value: 7, done: true}

生成器函数的嵌套 yield* f()

yield*后面的 Generator 函数(没有return语句时),等同于在 Generator 函数内部,部署一个for…of循环。

实际上,任何数据结构只要有 Iterator 接口,就可以被yield*遍历。

yield* 会将主函数的执行权交给被代理函数,之后的next()都是执行被代理函数里面的代码直至被代理函数执行完成,next()才会回到主函数中继续执行。

function* g(i){
	yield i+1;
	yield i+2;
	yield* g2(3);// 移交执行权
	yield* g2(3+i);// 移交执行权
	yield i+3
}
function* g2(k){
	yield 1+k;
	yield 2*k;
}
let it=g(5)

for (let i = 0; i < 8; i++) {
	console.log(it.next());
}

在这里插入图片描述

应用

部署Iterator接口

function* g(obj){
	const keys= Object.keys(obj);
	 for (let i=0; i < keys.length; i++) {
		 let key=keys[i];
		yield {key,value:obj[key]}
	}
}
let myObj = { foo: 3, bar: 7 };

for (let {key, value} of g(myObj)) {
  console.log(key, value);
}

当然如果只是单纯的遍历对象,使用Object.entries()更为简单

let myObj = { foo: 3, bar: 7 };
for (let [k,v] of Object.entries(myObj)) {
	console.log(k,v);
}

自动执行Generator函数 CO模块

function* g(){
	yield 1;
	yield 2;
	yield 3;
	
}

function autoRun(g){
	let it=g();
	let obj=it.next();
	while(!obj.done){
		obj=it.next();
	}
}
autoRun(g)

CO模块
co 模块是著名程序员 TJ Holowaychuk 于 2013 年 6 月发布的一个小工具,用于 Generator 函数的自动执行。co 模块可以让你不用编写 Generator 函数的执行器。

var co = require('co');
co(gen);

异步任务封装

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

Generator 函数封装了一个异步操作,该操作先读取一个远程接口,然后从 JSON 格式的数据解析信息。fetch返回的是一个 Promise 对象,因此要用then方法调用下一个next方法。为此可以通过Promise队列实现异步任务的同步执行。

参考文档:
Generator 函数的语法

最后

以上就是调皮蚂蚁为你收集整理的JS Generator function* 生成器函数的全部内容,希望文章能够帮你解决JS Generator function* 生成器函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部