文章目录
Generator 函数是 ES6 提供的一种 异步编程解决方案
(Generator 函数是一个状态机,封装了多个内部状态)
Generator 函数就是遍历器生成函数
function* 名称
体内 yield 表达式(状态等待执行 并返回)
一、next()方法
1.next不带参
function* fun(){
yield 1+1;
yield 2+2;
yield 3+3;
yield 4+4;
return 10; //替换最终的value:undefined
}
//执行该函数
let f=fun(); //执行之后返回遍历器
console.log(f.next()); //{value: 2, done: false}
console.log(f.next()); //{value: 4, done: false}
console.log(f.next()); //{value: 6, done: false}
console.log(f.next()); //{value: 8, done: false}
console.log(f.next()); //{value: 10, done: true}
//不加return,value:undefined

2.next带参
参数指的是上一次yeild表达式的返回值 (本身是undefined)
//next遍历带参 参数指的是上一次yeild表达式的返回值(本身是undefined)
function* method(){
let x=yield 1+2;
console.log(x);
let y=yield 3+x;
console.log(y);
return y+10;
}
let met=method();
console.log(met.next()); //{value: 3, done: false}
console.log(met.next(3)); //3 {value: 6, done: false}
console.log(met.next(8)); //8 {value: 18, done: true}
3.面试题
(1)yield表达式如果用在另一个表达式之中,必须放在圆括号里面
function* fun(){
let x=yield 5+(yield 1+2);
return x;
}
let xf=fun();
console.log(xf.next()); //{value: 3, done: false}
console.log(xf.next()); //{value: NaN, done: false} (5+undefined)
console.log(xf.next()); //{value: undefined, done: true}
console.log(xf.next()); //{value: 3, done: false}
console.log(xf.next(10)); //{value: 15, done: false} (5+10)
console.log(xf.next(5)); //{value: 5, done: true}
(2)Generator函数执行 返回遍历器 函数体并没有执行
function* fm(){
console.log("start");
console.log(1,`${yield}`);
console.log(2,`${yield}`);
console.log("end");
}
let f=fm(); //无返回值
f.next(); //start
f.next(5); //1 '5'
f.next(10); //2 '10'
f.next(); //end
console.log(f.next()); //start {value: undefined, done: false}
console.log(f.next('a')); //1 'a' {value: undefined, done: false}
console.log(f.next('b'));//2 'b' end {value: undefined, done: true}
(3)
function* fm(){
console.log(1,`${yield}`);
console.log(2,`${yield}`);
console.log("end");
}
let f=fm(); //无返回值
f.next(); //无返回值
f.next(5); //1 '5'
f.next(10); //2 '10' end
console.log(f.next()); // {value: undefined, done: false}
console.log(f.next('a')); //1 'a' {value: undefined, done: false}
console.log(f.next('b'));//2 'b' end {value: undefined, done: true}
二、for…of循环
1.for…of
for…of循环可以自动遍历 Generator 函数运行时生成的Iterator对象,且此时不再需要调用next方法
function* foo(){
yield 1;
yield 2;
yield 3;
yield 4;
return 5;
}
for(let v of foo()){
console.log(v); //1 2 3 4
}
一旦next方法的返回对象的done属性为true,for…of循环就会中止,且不包含该返回对象
所以上面代码的return语句返回的5,不包括在for…of循环之中
2.其他方法( … ,解构赋值 ,Array.from)
除了for…of循环以外,扩展运算符(…)、解构赋值和Array.from方法内部调用的,都是遍历器接口。
这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参数。
function* numbers () {
yield 1
yield 2
return 3
yield 4
}
// 扩展运算符
[...numbers()] // [1, 2]
// Array.from 方法
Array.from(numbers()) // [1, 2]
// 解构赋值
let [x, y] = numbers();
x // 1
y // 2
// for...of 循环
for (let n of numbers()) {
console.log(n)
}
// 1
// 2
三、异步读取
function* requCity(){
let result=yield Ajax('get','./city.json',null, function (res) {
console.log(aja.next(res)); //{value: Array(1), done: true}
})
let json=JSON.parse(result);
return json;
}
let aja=requCity();
aja.next();
city.json:
[
{"id":"1","name":"陕西","child":[
{"cid":"1-1","name":"西安"}
]}
]

四、throw() 抛出异常
Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获
(1)
var g = function* () {
try {
yield;
} catch (e) {
console.log('内部捕获', e);
}
};
var i = g();
i.next();
try {
i.throw('a');
i.throw('b');
} catch (e) {
console.log('外部捕获', e);
}
// 内部捕获 a
// 外部捕获 b
i第二次抛出错误,由于 Generator 函数内部的catch语句已经执行过了,不会再捕捉到这个错误了,所以被函数体外的catch语句捕获
(2)
function* method(){
try{
yield 1+2;
yield 2+3;
yield 3+4;
}
catch(e){
console.log(e.message);
}
}
let m=method();
console.log(m.next()); //{value: 3, done: false}
m.throw(new Error("出错了")); //出错了
五、return() 手动结束遍历
返回给定的值,并且终结遍历 Generator 函数
(1)有参
function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen();
g.next() // { value: 1, done: false }
g.return('foo') // { value: "foo", done: true }
g.next() // { value: undefined, done: true }
(2)无参
function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen();
g.next() // { value: 1, done: false }
g.return() // { value: undefined, done: true }
六、Generator嵌套
let a= function* () {
yield 'a';
yield 'b';
}
let b= function* () {
yield 1;
yield* a();
yield 2;
}
let bf=b();
console.log(bf.next()); //{value: 1, done: false}
console.log(bf.next()); //{value: 'a', done: false}
console.log(bf.next()); //{value: 'b', done: false}
console.log(bf.next()); //{value: 2, done: false}
console.log(bf.next()); //{value: undefined, done: true}
七、this
Generator 函数总是返回一个遍历器,ES6 规定这个遍历器是 Generator 函数的实例,也继承了 Generator 函数的prototype对象上的方法
(1)
function* g() {}
g.prototype.hello = function () {
return 'hi!';
};
let obj = g();
obj instanceof g // true
obj.hello() // 'hi!'
Generator 函数g返回的遍历器obj,是g的实例,而且继承了g.prototype
但是,如果把g当作普通的构造函数,并不会生效,因为g返回的总是遍历器对象,而不是this对象。
function* g() {
this.a = 11;
}
let obj = g();
obj.next();
obj.a // undefined
(2)Generator 函数也不能跟new命令一起用,会报错
function* F() {
yield this.x = 2;
yield this.y = 3;
}
new F()
// TypeError: F is not a constructor
(3)让 Generator 函数返回一个正常的对象实例,既可以用next方法,又可以获得正常的this
首先,生成一个空对象,使用call方法绑定 Generator 函数内部的this。这样,构造函数调用以后,这个空对象就是 Generator 函数的实例对象了。
function* F() {
this.a = 1;
yield this.b = 2;
yield this.c = 3;
}
var obj = {};
var f = F.call(obj);
f.next(); // Object {value: 2, done: false}
f.next(); // Object {value: 3, done: false}
f.next(); // Object {value: undefined, done: true}
obj.a // 1
obj.b // 2
obj.c // 3
八、Thunk 多参转单参

本文深入探讨了ES6中的Generator函数,包括next方法的使用、for...of循环、异步读取、throw方法处理异常、return方法手动结束遍历、Generator的嵌套以及this的相关特性。还介绍了如何通过Thunk转换多参数为单参数,以便更好地理解和应用Generator函数。

1143

被折叠的 条评论
为什么被折叠?



