2017-02-17 126 views

回答

10

首先,我首先說發電機是一個有點複雜的話題,因此在這裏給出一個完整的概述是不可能的。欲瞭解更多信息,我強烈建議凱爾辛普森的You Don't Know JS系列。第5冊(異步&性能)對發電機的輸入和輸出進行了精彩的討論。

根據你給出的具體例子!

首先,你的例子寫的代碼會顯示沒有區別只有它的正常運行。這裏有一個例子:

function* foo() { 
    yield 123; 
} 

function* bar() { 
    return yield 123; 
} 

var f = foo(); 
var b = bar(); 

f.next(); // {value: 123, done: false} 
f.next(); // {value: undefined, done: true} 
b.next(); // {value: 123, done: false} 
b.next(); // {value: undefined, done: true} 

正如你所看到的,我不是像普通函數那樣調用生成器。生成器本身返回一個生成器對象(一種迭代器的形式)。我們將該迭代器存儲在變量中,並使用.next()函數將迭代器推進到下一步(關鍵字yieldreturn)。

yield關鍵字允許我們將值傳遞給生成器,這就是您的示例運行方式不同的地方。下面是什麼樣子:

function* foo() { 
    yield 123; 
} 

function* bar() { 
    return yield 123; 
} 

var f = foo(); 
var b = bar(); 

// Start the generator and advance to the first `yield` 
f.next(); // {value: 123, done: false} 
b.next(); // {value: 123, done: false} 

/** Now that I'm at a `yield` statement I can pass a value into the `yield` 
* keyword. There aren't any more `yield` statements in either function, 
* so .next() will look for a return statement or return undefined if one 
* doesn't exist. Like so: 
*/ 
f.next(2); // {value: undefined, done: true} 
b.next(2); // {value: 2, done: true} 

注意foo()將返回undefined作爲一種價值,而bar()返回數字2。這是因爲我們傳遞到.next()調用中的值發送到return關鍵字並設置爲返回值。 foo()沒有明確的return語句,因此您將獲得默認的undefined行爲。

希望這有助於!

6

的區別是最後一個延續調用的結果值:

function* fooA() { 
    yield 123 
}; 
var a = fooA(); 
console.log(a.next(1)); // {done:false, value:123} 
console.log(a.next(2)); // {done:true, value:undefined} 

function* fooB() { 
    return 40 + (yield 123) 
}; 
var b = fooB(); 
console.log(b.next(1)); // {done:false, value:123} 
console.log(b.next(2)); // {done:true, value:42} 

大多數發電機不需要return價值,他們的目的是價值流的產生的副作用,當他們正在跑步。所有迭代器都屬於這種類型,如果它們運行在for of循環中,則結果僅表示結束,但該值將被丟棄。

然而,還有一些發生器的結果值是重要的,例如,當它們被用作描述異步過程的工具時(在一個polyfill中可以使用async/await承諾語法,或者還有很多其他的東西比如CSP)。在iterable上使用yield*時,您還會得到return ed值。

無論如何,return yield在一起聽起來不太有用。