JS的生成器的一些代码示例,示例中有详细注释,用于理解:
// EX1=======================================================>
console.log("EX1=======================================================>");
function* foo1(x) {
console.log("run foo2");
var y = x * (yield 5);
return y + 10;
}
var it = foo1(6); //此时并没有运行foo1(),只是构造了一个迭代器
console.log("create Iterator");
// 启动foo1(..),foo1()在yield语句处暂停,在这一点上第一个it.next()调用结束。
// 此时*foo1()仍在运行并且是活跃的,但处于暂停状态。
// 只有暂停的yield才能接受这样一个通过next(..)传递的值,
// 而在生成器的起始处我们调用第一个next()时,还没有暂停的yield来接受这样一个值。
// 规范和所有兼容浏览器都会默默丢弃传递给第一个next()的任何东西。
// 传值过去仍然不是一个好思路,因为你创建了沉默的无效代码,这会让人迷惑。
// 因此,启动生成器时一定要用不带参数的next()
console.log("skk => it.next()", it.next());
console.log("skk => it.next(7):", it.next(7)); // 52
// EX2=======================================================>
console.log("EX2=======================================================>");
// yield..和像a = 3这样的赋值表达式有同样的“表达式优先级”——类似于运算符优先级的概念。
// 这意味着yield..基本上可以出现在任何a = 3合法出现的位置。
// 因为yield关键字的优先级很低,且是右结合的。
function* foo2() {
console.log("启动foo2");
var a, b;
a = 3; // 合法
// b = 2 + a = 3; // 不合法
b = 2 + (a = 3); // 合法
yield 1; // 合法
console.log("yield 1, a= ", a);
// a = 2 + yield 1; // 不合法
a = 2 + (yield 2); // 合法
console.log("yield 2, a=", a);
return a;
}
var it = foo2();
console.log("ready next1");
console.log("next 1", it.next());
console.log("ready next2");
console.log("next 2", it.next());
console.log("ready next3");
console.log("next 3", it.next(5)); // 传参是合适的
// EX3=======================================================>
console.log("EX3=======================================================>");
// 执行生成器,比如foo(),并不实际在生成器中运行代码。相反,它会产生一个迭代器控制这个生成器执行其代码
function* foo3() {
console.log("inside 1 *foo3():", yield "B");
console.log("inside 2 *foo3():", yield "C");
return "D";
}
function* bar3() {
console.log("inside 1 *bar3():", yield "A");
// yield委托!
console.log("inside 2 *bar3():", yield* foo3());
console.log("inside 3 *bar3():", yield "E");
// yield委托!
console.log("inside 4 *[1,2,7]:", yield* [1, 2, 7]);
return "F";
}
var it = bar3();
console.log("outside:", it.next());
// outside: A
console.log("outside:", it.next(11));
// inside 1*bar(): 11
// outside: B
console.log("outside:", it.next(22));
// inside 1*foo(): 22
// outside: C
console.log("outside:", it.next(33));
// inside 2*foo(): 33
// inside 2*bar(): D
// outside: E
console.log("outside:", it.next(44));
// inside 3*bar(): 44
// outside: 1
console.log("outside:", it.next(55));
// outside: 2
console.log("outside:", it.next(66));
// outside: 3
console.log("outside:", it.next(77));
// inside 4 *[1,2,7]: undefined
// outside: F
// EX4=======================================================>
console.log("EX4=======================================================>");
function* foo4() {
console.log("foo4 run");
var arr = [yield 11, yield 22, yield 33]; //即使声明了也要用next
// console.log( arr, yield 4 );
console.log("foo4 return");
return "dk";
}
var it = foo4();
console.log("next 1", it.next());
console.log("next 2", it.next());
console.log("next 3", it.next());
console.log("next 4", it.next());
// EX5=======================================================>
console.log("EX5=======================================================>");
function* foo5(x) {
if (x < 3) {
x = yield* foo5(x + 1);
}
console.log("foo5 out x=", x);
return x * 2;
}
var it = foo5(1);
// 执行next后生成器没有真正暂停,因为并没有yield ..表达式。
// 相反,yield *只是通过递归调用保存当前的迭代步骤。所以,只要一次调用迭代器的next()函数就运行了整个生成器
console.log("it.next =", it.next()); // { value: 24, done: true }
// EX6=======================================================>
console.log("EX6=======================================================>");
// 迭代器的本质
// 每个yield..从(1, 2, 3)中发出一个值,更直接地说,它是暂停生成器来等待一个值。
// 换句话说几乎等价于在问 "这里我应该用什么值?请回复"
function *foo6() {
var x = yield 1;
var y = yield 2;
var z = yield 3;
console.log("foo6 return", x, y, z );
}
// 生成器函数引用(比如foo6)自己并不是一个iterable, 需要通过foo6()执行它才能得到一个迭代器
for (var v of foo6()) {
console.log( "v=", v ); // 如果yield后面是变量的话,则返回undefined
}
// 创建迭代器
var it = foo6();
// 第一个next()调用初始的暂停状态启动生成器,运行直到第一个yield。在调用第一个next()的时候,
// 并没有yield..表达式等待完成。如果向第一个next()调用传入一个值,这个值会马上被丢弃,因为并没有yield等待接收这个值
console.log("next 1", it.next()); // next 1 { value: 1, done: false }
// 需要给x一个什么值?给“XX”吧
console.log("next 2", it.next("XX")); // next 2 { value: 2, done: false }
// 需要给y一个什么值?给“YY”吧
console.log("next 3", it.next("YY")); // next 3 { value: 3, done: false }
// 需要给z一个什么值?给“ZZ”吧
console.log("next 4", it.next("ZZ")); // next 4 { value: undefined, done: true }, foo6没有return值,value为undefined
最后更新于 2023-11-17 16:33:17 by twotwolucky