它封裝多個內部狀態,而 yield 是一個暫停標誌
function* generator() {
yield 'state1';
yield 'state2';
}
function* speak() {
yield 'hello';
yield 'world';
}
const iterator = speak();
next()
遍歷狀態function* speak() {
yield 'hello';
yield 'world';
}
const i = speak();
i.next(); // { value: 'hello', done: false }
i.next(); // { value: 'world', done: false }
i.next(); // { value: undefined, done: true }
如果 generator 有 return
值
function* speak() {
yield 'hello';
yield 'world';
return '!';
}
const i = speak();
i.next(); // { value: 'hello', done: false }
i.next(); // { value: 'world', done: false }
i.next(); // { value: '!', done: true }
i.next(); // { value: undefined, done: true }
yield
後面的表達式,只有被呼叫 next()
才會執行
function getName() {
console.log('My name is world.');
return 'world';
}
function* speak() {
yield 'hello ' + getName();
}
const i = speak();
i.next(); // My name is world.
// { value: 'hello world', done: false }
// 不一定要使用 yield
function* speak() {}
// 但是 yield 一定要在 generator function 中使用
function speak() {
yield 'hello world'; // Error!
}
// 在表達式中必須加括弧
console.log('hello' + (yield 'world'));
// 在參數中不用
getName(yield 'Who are you?');
next()
中傳入參數,與 generator 互動function* conversation() {
const name = yield 'What\'s your name?';
yield `Ok, your name is ${name}, right?`;
}
const i = conversation();
i.next().value; // What's your name?
i.next('Jason').value; // Ok, your name is Jason, right?
第一個 next() 是不能給參數的
const i = conversation();
i.next().value;
i.next('Jason').value;
小試題:會印出什麼呢?
function* foo(x) {
const y = 2 * (yield (x + 1));
const z = yield (y / 3);
return (x + y + z);
}
const i = foo(5);
console.log(i.next().value);
console.log(i.next(12).value);
console.log(i.next(13).value);
function* foo(x) {
const y = 2 * (yield (x + 1));
const z = yield (y / 3);
return (x + y + z);
}
const i = foo(5);
console.log(i.next().value); // 6
console.log(i.next(12).value); // 8
console.log(i.next(13).value); // 42
next()
遍歷狀態next()
中傳入參數,與 generator 互動注意:沒有 return
值
function *foo() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
}
for (let v of foo()) {
console.log(v);
}
// 1 2 3 4 5
一個 fibonacci 例子
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
if (n > 1000) break;
console.log(n);
}
function* numbers () {
yield 1
yield 2
return 3
yield 4
}
[...numbers()] // [1, 2]
Array.from(numbers()) // [1, 2]
let [x, y] = numbers(); // x=1, y=2
for (let n of numbers()) {
console.log(n);
}
// 1 2
function* g() {
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
throw
被捕獲以後,會附帶執行下一條 yield
語句
function* g() {
try {
yield console.log('a');
} catch (e) {
// ...
}
yield console.log('b');
yield console.log('c');
}
var i = g();
i.next(); // a
i.throw(); // b
i.next(); // c
function* g() {
yield 1;
yield 2;
yield 3;
}
var i = g();
i.next(); // { value: 1, done: false }
i.return('foo'); // { value: 'foo', done: true }
i.next(); // { value: undefined, done: true }
function* numbers() {
yield 1;
try {
yield 2;
yield 3;
} finally {
yield 4;
yield 5;
}
yield 6;
}
var i = numbers()
i.next(); // { done: false, value: 1 }
i.next(); // { done: false, value: 2 }
i.return(7); // { done: false, value: 4 }
i.next(); // { done: false, value: 5 }
i.next(); // { done: true, value: 7 }
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
for (let v of bar()) {
console.log(v);
}
// x a b y
陣列是 iterator
function* g() {
yield* ['a', 'b', 'c'];
}
g().next() // { value: 'a', done: false }
字串也是
let read = (function* () {
yield 'hello';
yield* 'hello';
})();
read.next().value // 'hello'
read.next().value // 'h'
接收 yield*
的 return
function* foo() {
yield 2;
yield 3;
return 'foo';
}
function* bar() {
yield 1;
var v = yield* foo();
console.log('v: ' + v);
yield 4;
}
var i = bar();
i.next(); // { value: 1, done: false }
i.next(); // { value: 2, done: false }
i.next(); // { value: 3, done: false }
i.next(); // 'v: foo'
// { value: 4, done: false }
i.next(); // { value: undefined, done: true }
const obj = {
* myGeneratorMethod() {
···
}
};
gernerator 回傳的是 gernerator 實例
function* g() {}
g.prototype.hello = function () {
return 'hi!';
};
const obj = g();
obj instanceof g; // true
obj.hello(); // 'hi!'
generator 返回的是遍歷器,不是 this
function* g() {
this.a = 11;
}
let obj = g();
obj.a; // undefined
不能使用 new
function* F() {
yield this.x = 2;
yield this.y = 3;
}
new F()
// TypeError: F is not a constructor