JavaScript中函數后面打星號方式聲明
function*
?這種聲明方式(function
關鍵字后跟一個星號)會定義一個生成器函數?(generator function),它返回一個 ?Generator
??對象。
function* generator(i) {
yield i;
yield i + 10;
}
const gen = generator(10);
console.log(gen.next().value);
// expected output: 10
console.log(gen.next().value);
// expected output: 20
語法
function* name([param[, param[, ... param]]]) { statements }
name
- 函數名
param
- 要傳遞給函數的一個參數的名稱,一個函數最多可以有255個參數。
statements
- 普通JS語句。
描述
生成器函數在執行時能暫停,后面又能從暫停處繼續執行。
調用一個生成器函數并不會馬上執行它里面的語句,而是返回一個這個生成器的?迭代器?(?iterator?)對象。當這個迭代器的?next()?
方法被首次(后續)調用時,其內的語句會執行到第一個(后續)出現yield
的位置為止,yield
?后緊跟迭代器要返回的值。或者如果用的是?yield*
(多了個星號),則表示將執行權移交給另一個生成器函數(當前生成器暫停執行)。
next()
方法返回一個對象,這個對象包含兩個屬性:value 和 done,value 屬性表示本次?yield?
表達式的返回值,done 屬性為布爾類型,表示生成器后續是否還有?yield?
語句,即生成器函數是否已經執行完畢并返回。
調用?next()
方法時,如果傳入了參數,那么這個參數會傳給上一條執行的 yield語句左邊的變量,例如下面例子中的?x?
:
function *gen(){
yield 10;
x=yield 'foo';
yield x;
}
var gen_obj=gen();
console.log(gen_obj.next());// 執行 yield 10,返回 10
console.log(gen_obj.next());// 執行 yield 'foo',返回 'foo'
console.log(gen_obj.next(100));// 將 100 賦給上一條 yield 'foo' 的左值,即執行 x=100,返回 100
console.log(gen_obj.next());// 執行完畢,value 為 undefined,done 為 true
當在生成器函數中顯式?return?
時,會導致生成器立即變為完成狀態,即調用?next()
?方法返回的對象的?done?
為?true
。如果?return?
后面跟了一個值,那么這個值會作為當前調用?next()
?方法返回的 value 值。
示例
簡單示例
function* idMaker(){
var index = 0;
while(index<3)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined
生成器也可以接收參數:
function* idMaker(){
var index = arguments[0] || 0;
while(true)
yield index++;
}
var gen = idMaker(5);
console.log(gen.next().value); // 5
console.log(gen.next().value); // 6
yield*的示例
function* anotherGenerator(i) {
yield i + 1;
yield i + 2;
yield i + 3;
}
function* generator(i){
yield i;
yield* anotherGenerator(i);// 移交執行權
yield i + 10;
}
var gen = generator(10);
console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
?傳遞參數
function *createIterator() {
let first = yield 1;
let second = yield first + 2; // 4 + 2
// first =4 是next(4)將參數賦給上一條的
yield second + 3; // 5 + 3
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next(4)); // "{ value: 6, done: false }"
console.log(iterator.next(5)); // "{ value: 8, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
顯式返回
function* yieldAndReturn() {
yield "Y";
return "R";//顯式返回處,可以觀察到 done 也立即變為了 true
yield "unreachable";// 不會被執行了
}
var gen = yieldAndReturn()
console.log(gen.next()); // { value: "Y", done: false }
console.log(gen.next()); // { value: "R", done: true }
console.log(gen.next()); // { value: undefined, done: true }
生成器函數不能當構造器使用
function* f() {}
var obj = new f; // throws "TypeError: f is not a constructor"
?使用迭代器遍歷二維數組并轉換成一維數組:
function* iterArr(arr) { //迭代器返回一個迭代器對象
if (Array.isArray(arr)) { // 內節點
for(let i=0; i < arr.length; i++) {
yield* iterArr(arr[i]); // (*)遞歸
}
} else { // 離開
yield arr;
}
}
// 使用 for-of 遍歷:
var arr = ['a', ['b', 'c'], ['d', 'e']];
for(var x of iterArr(arr)) {
console.log(x); // a b c d e
}
// 或者直接將迭代器展開:
var arr = [ 'a', ['b',[ 'c', ['d', 'e']]]];
var gen = iterArr(arr);
arr = [...gen]; // ["a", "b", "c", "d", "e"]
?兼容性
版權聲明:
作者:applek
鏈接:http://www.yydfqli.cn/jsfunxing.html
文章版權歸作者所有,未經允許請勿轉載。
THE END