成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

ES6-迭代器(iterator)和生成器(generator)- 迭代器和生成器的高級用法

Edison / 765人閱讀

摘要:在生成器中使用語句生成器也是函數(shù),所以它也可以使用語句。只是由于生成器本身的特性,其內(nèi)部的的行為會和一般函數(shù)有些差別。

前面2篇系列文章講解了迭代器和生成器的最常用,最基礎(chǔ)的用法;這篇來討論迭代器和生成器的一些稍稍高級一點的用法:

1: 給迭代器的next()方法傳參
2: 從迭代器中拋出錯誤
3: 在生成器中使用return語句
4: 委托生成器(組合生成器或者生成器組合?)

1: 給迭代器的next()方法傳參
在前面2篇系列文章中我們使用的next()方法都是沒有傳參的,調(diào)用next()會依次返回迭代器里面的值。但是,實際上我們是可以給next()方法傳參數(shù)的,那在這種情況下我們會得到什么樣的結(jié)果呢?

function* createIterator() {
    let first = yield 1;
    console.log(`first: ${first}`);
    let second = yield first + 2;
    console.log(`second: ${second}`);
    let third = yield second + 3;
}
let iterator = createIterator();
console.log(iterator.next(0));
console.log(iterator.next(4));
console.log(iterator.next(5));
console.log(iterator.next());

我們得到下面的輸出結(jié)果:

{value: 1, done: false}
first: 4
{value: 6, done: false}
second: 5
{value: 8, done: false}
{value: undefined, done: true}

在第二次和第三次的next調(diào)用中我們分別傳入?yún)?shù)4和5,而4和5也分別被賦值給了變量first和second。當我們執(zhí)行:
iterator.next(4)的時候,生成器內(nèi)部執(zhí)行的代碼實際上是:

let first = 4; yield 4 + 2; //所以我們得到 {value: 6, done: false}

iterator.next(5)的時候,生成器內(nèi)部執(zhí)行的代碼實際上是:

let second = 5; yield 5 + 3; //所以我們得到 {value: 8, done: false}

看下面一個圖或許能更直觀一些:

        以上截圖來自書 Understanding ECMAScript 6

但是上面的例子中,我們也看到一個有趣的現(xiàn)象,就是我們第一次調(diào)用next的時候,是傳了參數(shù)0的iterator.next(0),但是我們依然得到了結(jié)果{value: 1, done: false}。這是因為第一次調(diào)用next(),無論傳遞什么參數(shù)總是會被丟棄,所以給第一次調(diào)用的next()方法傳值是無意義的。
或許你看到這里也還不是完全明白了給next()傳參時,生成器內(nèi)部到底是怎樣工作。接下來我們再看一個例子,這一次我們在第3次調(diào)用next()的時候,不傳參數(shù),看會發(fā)生什么:

function* createIterator() {
    let first = yield 1;
    console.log(`first: ${first}`);
    let second = yield first + 2;
    console.log(`second: ${second}`);
    let third = yield second + 3;
}
let iterator = createIterator();
console.log(iterator.next(0));
console.log(iterator.next(4));
console.log(iterator.next());
console.log(iterator.next());

我們得到的輸出結(jié)果是:

{value: 1, done: false}
first: 4
{value: 6, done: false}
second: undefined
{value: NaN, done: false}
{value: undefined, done: true}

在第三次的next調(diào)用中,我們并沒有傳遞任何參數(shù),生成器內(nèi)部的執(zhí)行情況就是:

let second; yield undefined + 2; //所以我們得到結(jié)果{value: NaN, done: false}

其實從這里例子我們也可以看出,在生成器內(nèi)部,yield執(zhí)行的結(jié)果并不會被保存下來賦值給內(nèi)部的變量,例如這里我們在第三次沒有給next()傳遞參數(shù),那么second的值就是undefined,而不是第二次yield執(zhí)行結(jié)果的value 6。

2: 從迭代器中拋出錯誤
我們知道一般的函數(shù)的執(zhí)行結(jié)果有2種:

1: 返回一個值
2: 拋出一個錯誤

生成器函數(shù)作為一種特殊的函數(shù),但是它本身也是函數(shù),所以它也可以拋出錯誤。只是它拋出錯誤的時間與一般函數(shù)不同,看一下下面的代碼:

function* createIterator() {
    let first = yield 1;
    let second = yield first + 2;
    yield second + 3;
}
let iterator = createIterator();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next(4)); //{value: 6, done: false}
console.log(iterator.throw(new Error("Boom"))); //Uncaught Error: Boom

在生成器內(nèi)部代碼執(zhí)行情況如下圖所示:

        以上截圖來自書 Understanding ECMAScript 6

當我們拋出錯誤之后,代碼就停止了。let second語句并不會被執(zhí)行到。
但是生成器里面的throw()它會像yield一樣,也會返回一個結(jié)果。我們可以像一般函數(shù)一樣catch這個錯誤,并且之后的代碼依然可以得到執(zhí)行:

function* createIterator() {
    let first = yield 1;
    let second;
    try {
        second = yield first + 2;
    } catch (error) {
        second = 6;
    }
    yield second + 3;
}

let iterator = createIterator();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next(4)); //{value: 6, done: false}
console.log(iterator.throw(new Error("Boom"))); //{value: 9, done: false}
console.log(iterator.next());//{value: undefined, done: true}

在這個例子中,我們catch了錯誤之后,給second賦值6,它后面的代碼yield second + 3;也依然可以得到執(zhí)行。
3: 在生成器中使用return語句
生成器也是函數(shù),所以它也可以使用return語句。只是由于生成器本身的特性,其內(nèi)部的return的行為會和一般函數(shù)有些差別。我們先來看兩個例子,就能從中窺探一二:
例1:

function* createIterator() {
    yield 1;
    return;
    yield 2;

}
let iterator = createIterator();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next()); //{value: undefined, done: true}
console.log(iterator.next());//{value: undefined, done: true}

例2:

function* createIterator() {
    yield 1;
    return 2;
    yield 3;

}
let iterator = createIterator();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next()); //{value: 2, done: true}
console.log(iterator.next()); //{value: undefined, done: true}

上面的例1只是使用了return語句,然后后面沒有跟任何值,例2代碼就return了一個數(shù)字,我們從調(diào)用next()的結(jié)果可以看到:

1: return語句會終止返回迭代器里面本可以再迭代的值,會把done設(shè)置為false
2: return語句如果指定一個值,那么此次結(jié)果的value會被賦為此值;如果沒有指定,那value為undefined

4: 委托生成器(組合生成器或者生成器組合?)
單個的生成器函數(shù)里,yield后面往往跟一些我們常用的數(shù)據(jù)類型;但是,我們也可以yield 一個生成器函數(shù),這樣的操作就叫委托生成器。先看一個代碼的例子:

function *createNumberIterator() {
    yield 1;
    yield 2;

}
function *createColorIterator() {
    yield "red";
    yield "yellow";

}
function *createCombinedIterator() {
    yield *createNumberIterator();
    yield *createColorIterator();

}
let combinedIterator = createCombinedIterator();
console.log(combinedIterator.next());//{value: 1, done: false}
console.log(combinedIterator.next());//{value: 2, done: false}
console.log(combinedIterator.next());//{value: "red", done: false}
console.log(combinedIterator.next());//{value: "yellow", done: false}
console.log(combinedIterator.next());//{value: undefined, done: true}

上面的這個示例,我們創(chuàng)建兩個不同的生成器函數(shù)createNumberIterator()和createColorIterator(),之后在createCombinedIterator()函數(shù)里通過yield語句調(diào)用前面的2個生成器函數(shù),這樣createCombinedIterator()就成了一個擁有以上2個生成器的迭代器的生成器,調(diào)用*createCombinedIterator()的next(),就跟一般的生成器的next()方法的行為一樣。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/110287.html

Failed to recv the data from server completely (SIZE:0/8, REASON:closed)