我是靠谱客的博主 难过小蘑菇,最近开发中收集的这篇文章主要介绍Generator生成器详解generator函数迭代器对象的方法Generator 函数的thisgenerator函数应用注意点,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Generator生成器详解

  • generator函数
    • 定义
  • 迭代器对象的方法
    • next方法
    • throw方法
    • return方法
    • next、throw、return共同点
    • yield*表达式
  • Generator 函数的this
  • generator函数应用
    • 状态机
    • 部署iterator接口
    • 异步操作的同步化表达
    • 流程控制
  • 注意点
    • 注意点一
    • 注意点二
    • 注意点三
    • 注意点四

generator函数

定义

定义:
1、function关键字和函数名之间加上*号
2、函数内部使用yield表达式来暂停函数执行,并将表达式的值返回

function* f(){
yield 'hello ';
yield 'javascript';
return "test";
}
var obj = f() //生成器函数执行后返回一个迭代器对象,内部代码不会立即执行
obj.next() // {value: "hello ", done: false}
obj.next() // {value: "javascript", done: false}
obj.next() // {value: "test", done: true}	

执行流程: 调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束

迭代器对象的方法

next方法

next方法的逻辑:
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。

next方法的参数:
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。

function* f(){
console.log(3 + (yield));
}
var g = f()
g.next();
//g.next(); //打印NaN
g.next(7); //打印7

throw方法

enerator 函数返回的遍历器对象,都有一个throw方法, 用于在当前的yield处抛出异常,可以接收一个参数当做抛出的异常。如果内部不捕获,则向外抛出

function* f() {
try {
yield;
} catch (e) {
console.log('内部捕获', e);
}
};
var iter = f();
iter .next();
try {
iter.throw('a');
iter.throw('b');
} catch (e) {
console.log('外部捕获', e);
}
// 内部捕获 a
// 外部捕获 b

return方法

Generator 函数返回的遍历器对象,还有一个return()方法,可以返回给定的值,并且终结遍历 Generator 函数。

function* f() {
yield 1;
yield 2;
yield 3;
}
var gen = f();
gen.next()
// { value: 1, done: false }
gen.return('foo') // { value: "foo", done: true }
gen next()
// { value: undefined, done: true }

next、throw、return共同点

next()、throw()、return()这三个方法的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式。

next()是将yield表达式替换成一个值。

const g = function* (x, y) {
let result = yield x + y;
return result;
};
const gen = g(1, 2);
gen.next(); // Object {value: 3, done: false}
gen.next(1); // Object {value: 1, done: true}
// 相当于将 let result = yield x + y
// 替换成 let result = 1;

throw()是将yield表达式替换成一个throw语句。

gen.throw(new Error('出错了')); // Uncaught Error: 出错了
// 相当于将 let result = yield x + y
// 替换成 let result = throw(new Error('出错了'));

return()是将yield表达式替换成一个return语句。

gen.return(2); // Object {value: 2, done: true}
// 相当于将 let result = yield x + y
// 替换成 let result = return 2;

yield*表达式

yield*后面接iterable对象, 默认会调用它的迭代器方法,用于遍历对象。

例子一
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
yield* foo();
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* foo() {
yield 2;
yield 3;
return "foo"; //作为yield*表达式的返回值
}
function* bar() {
yield 1;
var v = yield* foo(); // v="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}

Generator 函数的this

Generator 函数总是返回一个迭代器,ES6 规定这个迭代器是 Generator 函数的实例,也继承了 Generator 函数的prototype对象上的方法

function* f(){}
f.prototype.hello = function(){
console.log('hello');
}
var gen = f();
gen instanceof f // true
gen.hello() // hello

f函数内部的this不是指向该迭代器对象。

function* f() {
this.a = 11;
}
let gen = f();
gen.next();
gen.a // undefined

Generator 函数也不能跟new命令一起用,会报错。

function* F() {
yield this.x = 2;
yield this.y = 3;
}
new F() // TypeError: F is not a constructor

generator函数应用

状态机

//es5状态机的实现
var ticking = true;
var clock = function() {
if (ticking)
console.log('Tick!');
else
console.log('Tock!');
ticking = !ticking;
}
//es6状态机的实现
var clock = function* () {
while(true){
console.log('Tick!');
yield;
console.log('Tock!');
yield;
}
}

部署iterator接口

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] //[1、2、3]

异步操作的同步化表达

function* main() {
var result = yield request("http://www.baidu.com");
var resp = JSON.parse(result);
console.log(resp.value);
}
function request(url) {
makeAjaxCall(url, function(response){
it.next(response);
});
}
function makeAjaxCall(url, callbackfn){
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
callbackfn(xhr.responseText);
}
}
xhr.send();
}
var it = main();
it.next();

流程控制

如果有一个多步操作非常耗时,采用回调函数,可能会写成下面这样。

step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});

采用 Promise 改写上面的代码。

Promise.resolve(step1)
.then(step2)
.then(step3)
.then(step4)
.then(function (value4) {
// Do something with value4
}, function (error) {
// Handle any error from step1 through step4
})

Generator 函数可以进一步改善代码运行流程。

function* longRunningTask(value1) {
try {
var value2 = yield step1(value1);
var value3 = yield step2(value2);
var value4 = yield step3(value3);
var value5 = yield step4(value4);
// Do something with value4
} catch (e) {
// Handle any error from step1 through step4
}
}

注意点

注意点一

yield表达式只能出现在generator函数中

function f(){
yield; //error,只能出现在generator函数中
}

注意点二

yield表达式如果在另一个表达式中,需要加括号

function* demo() {
console.log('Hello' + yield 'world'); // error
console.log('Hello' + (yield 'world')); // OK
}

注意点三

yield表达式可以作为参数或者出现在赋值号=的右边

function* demo() {
foo(yield 'a'); // OK
let input = yield; // OK
}

注意点四

当调用return函数时,如果当前的yield表达式在try…finally语句中,则会立刻进入finally代码块中执行,直到代码块结束,最后才返回之前return函数的参数

function* numbers () {
yield 1;
try {
yield 2;
yield 3;
} finally {
yield 4;
yield 5;
}
yield 6;
}
var g = numbers();
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.return(7) // { value: 4, done: false }
g.next() // { value: 5, done: false }
g.next() // { value: 7, done: true }

最后

以上就是难过小蘑菇为你收集整理的Generator生成器详解generator函数迭代器对象的方法Generator 函数的thisgenerator函数应用注意点的全部内容,希望文章能够帮你解决Generator生成器详解generator函数迭代器对象的方法Generator 函数的thisgenerator函数应用注意点所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部