国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ES6之Iterator、Generator

ashe / 1567人閱讀

摘要:舉個(gè)例子遍歷器生成函數(shù),作用就是返回一個(gè)遍歷器對(duì)象,方法返回一個(gè)對(duì)象,表示當(dāng)前數(shù)據(jù)成員的信息。該對(duì)象本身也具有屬性,執(zhí)行后返回自身。

Iterator的作用

一是為各種數(shù)據(jù)結(jié)構(gòu),提供一個(gè)統(tǒng)一的、簡(jiǎn)便的訪問(wèn)接口;(統(tǒng)一)
二是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列;(按序
三是ES6創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator接口主要供for...of消費(fèi)。
舉個(gè)例子:遍歷器生成函數(shù),作用就是返回一個(gè)遍歷器對(duì)象,next方法返回一個(gè)對(duì)象,表示當(dāng)前數(shù)據(jù)成員的信息。這個(gè)對(duì)象具有value和done兩個(gè)屬性,value屬性返回當(dāng)前位置的成員,done屬性是一個(gè)布爾值,表示遍歷是否結(jié)束

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

對(duì)于遍歷器對(duì)象來(lái)說(shuō),done: false和value: undefined屬性都是可以省略的,所以上述代碼可以簡(jiǎn)寫為:

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++]} :
        {done: true};
    }
  };
}

Iterator 只是把接口規(guī)格加到數(shù)據(jù)結(jié)構(gòu)之上,所以,遍歷器與它所遍歷的那個(gè)數(shù)據(jù)結(jié)構(gòu),實(shí)際上是分開的,完全可以寫出沒(méi)有對(duì)應(yīng)數(shù)據(jù)結(jié)構(gòu)的遍歷器對(duì)象,或者說(shuō)用遍歷器對(duì)象模擬出數(shù)據(jù)結(jié)構(gòu)

Iterator接口

默認(rèn)的 Iterator 接口部署在數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator屬性,Symbol.iterator屬性本身是一個(gè)函數(shù),就是當(dāng)前數(shù)據(jù)結(jié)構(gòu)默認(rèn)的遍歷器生成函數(shù)。執(zhí)行這個(gè)函數(shù),就會(huì)返回一個(gè)遍歷器
原生具備 Iterator 接口的數(shù)據(jù)結(jié)構(gòu)如下:
1)Array
2)Map
3)Set
4)String
5)TypedArray
6)函數(shù)的 arguments 對(duì)象
對(duì)于部署了Iterator接口的數(shù)據(jù)結(jié)構(gòu)除了可以使用for of循環(huán)之外,可以用while判斷對(duì)象的done屬性進(jìn)行循環(huán)遍歷
怎么樣使用原生的遍歷器呢?

let arr = ["a", "b", "c"];
let iter = arr[Symbol.iterator]();

iter.next()

//第二個(gè)例子:
var someString = "hi";
typeof someString[Symbol.iterator]
// "function"

var iterator = someString[Symbol.iterator]();

iterator.next()  // { value: "h", done: false }

對(duì)于類似數(shù)組的對(duì)象應(yīng)該怎樣調(diào)用數(shù)組的Symbol.iterator方法?

let iterable = {
  0: "a",
  1: "b",
  2: "c",
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]//這句話是重點(diǎn)
};
for (let item of iterable) {
  console.log(item); // "a", "b", "c"
}
使用Iterator的場(chǎng)景

解構(gòu)賦值

let set = new Set().add("a").add("b").add("c");
let [first, ...rest] = set;
// first="a"; rest=["b","c"];
//對(duì)數(shù)組和 Set 結(jié)構(gòu)進(jìn)行解構(gòu)賦值時(shí),會(huì)默認(rèn)調(diào)用Symbol.iterator方法

擴(kuò)展運(yùn)算符

var str = "hello";
[...str] //  ["h","e","l","l","o"]
//擴(kuò)展運(yùn)算符(...)也會(huì)調(diào)用默認(rèn)的 Iterator 接口

yield*

let generator = function* () {
  yield 1;
  yield* [2,3,4];
  yield 5;
};

var iterator = generator();

iterator.next()
遍歷器的return和throw方法

遍歷器對(duì)象生成函數(shù),next方法是必須部署的,return方法和throw方法是否部署是可選的。return方法必須返回一個(gè)對(duì)象

function readLinesSync(file) {
  return {
    next() {
      if (file.isAtEndOfFile()) {
        file.close();
        return { done: true };
      }
    },
    return() {
      file.close();
      return { done: true };
    },
  };
}
for (let line of readLinesSync(fileName)) {
  console.log(line);
  break;//我們讓文件的遍歷提前返回,這樣就會(huì)觸發(fā)執(zhí)行return方法
}
for of 循環(huán)優(yōu)點(diǎn)

forEach沒(méi)辦法跳出循環(huán),也就是說(shuō)在forEach當(dāng)中break命令或return命令都不能奏效
for...in循環(huán)不僅遍歷數(shù)字鍵名,還會(huì)遍歷手動(dòng)添加的其他鍵,甚至包括原型鏈上的鍵,而且for in 是沒(méi)有順序的(也就是說(shuō)for...in循環(huán)主要是為遍歷對(duì)象而設(shè)計(jì)的,不適用于遍歷數(shù)組)

小訣竅:
1、并不是所有類似數(shù)組的對(duì)象都具有 Iterator 接口,一個(gè)簡(jiǎn)便的解決方法,就是使用Array.from方法將其轉(zhuǎn)為數(shù)組

let arrayLike = { length: 2, 0: "a", 1: "b" };

// 報(bào)錯(cuò)
for (let x of arrayLike) {
  console.log(x);
}

// 正確
for (let x of Array.from(arrayLike)) {
  console.log(x);
}

2、因?yàn)槠胀▽?duì)象并沒(méi)有部署Iterator接口,所以是無(wú)法使用for of循環(huán)的,用以下兩種方案解決:

for (var key of Object.keys(someObject)) {
  console.log(key + ": " + someObject[key]);
}

//第二種方式:
function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}
for (let [key, value] of entries(obj)) {
  console.log(key, "->", value);
}
//第三種方式:
function* objectEntries(obj) {
  let propKeys = Reflect.ownKeys(obj);
  for (let propKey of propKeys) {
    yield [propKey, obj[propKey]];
  }
}
for (let [key, value] of objectEntries(obj)) {
  console.log(`${key}: ${value}`);
}
//或者也可以這樣
let jane = { first: "Jane", last: "Doe" };

jane[Symbol.iterator] = objectEntries;//這句話是重點(diǎn)將 Generator 函數(shù)加到對(duì)象的Symbol.iterator屬性上面

for (let [key, value] of jane) {
  console.log(`${key}: ${value}`);
}
Generator簡(jiǎn)介

在我看來(lái)Generator就是為了異步編程提供一種解決方案;
Generator 函數(shù)是一個(gè)普通函數(shù),事實(shí)上它是遍歷器生成函數(shù),但有幾個(gè)特性:
1、function關(guān)鍵字與函數(shù)名之間有一個(gè)星號(hào)(星號(hào)緊跟在function關(guān)鍵字后面);
2、函數(shù)體內(nèi)部使用yield表達(dá)式,定義不同的內(nèi)部狀態(tài)(yield在英語(yǔ)里的意思就是“產(chǎn)出” 1)yield只能在Generator函數(shù)中使用;2)yield表達(dá)式如果用在另一個(gè)表達(dá)式之中,必須放在圓括號(hào)里面;3)yield表達(dá)式用作函數(shù)參數(shù)或放在賦值表達(dá)式的右邊,可以不加括號(hào));
3、可以把Generator函數(shù)理解為狀態(tài)機(jī),調(diào)用 Generator 函數(shù)后,該函數(shù)并不執(zhí)行,返回的也不是函數(shù)運(yùn)行結(jié)果,而是一個(gè)指向內(nèi)部狀態(tài)的指針對(duì)象,每次調(diào)用next方法,內(nèi)部指針就從函數(shù)頭部或上一次停下來(lái)的地方開始執(zhí)行,直到遇到下一個(gè)yield表達(dá)式(或return語(yǔ)句)為止;Generator 函數(shù)是分段執(zhí)行的,yield表達(dá)式是暫停執(zhí)行的標(biāo)記,而next方法可以恢復(fù)執(zhí)行。

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

[...myIterable]

Generator 函數(shù)執(zhí)行后,返回一個(gè)遍歷器對(duì)象。該對(duì)象本身也具有Symbol.iterator屬性,執(zhí)行后返回自身。

function* gen(){
  // some code
}

var g = gen();

g[Symbol.iterator]() === g
Generator中next方法的參數(shù)

通過(guò)next方法的參數(shù),就有辦法在 Generator 函數(shù)開始運(yùn)行之后,繼續(xù)向函數(shù)體內(nèi)部注入值
由于next方法的參數(shù)表示上一個(gè)yield表達(dá)式的返回值,所以第一次使用next方法時(shí),不能帶有參數(shù)。V8 引擎直接忽略第一次使用next方法時(shí)的參數(shù),只有從第二次使用next方法開始,參數(shù)才是有效的
舉個(gè)簡(jiǎn)單的例子吧:

function* dataConsumer() {
  console.log("Started");
  console.log(`1. ${yield}`);
  console.log(`2. ${yield}`);
  return "result";
}

let genObj = dataConsumer();
genObj.next();
// Started
genObj.next("a")
// 1. a
genObj.next("b")
// 2. b

復(fù)雜一點(diǎn)的:

function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}

var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
//解釋一下結(jié)果y=2*12 所以返回的是24/3
b.next(13) // { value:42, done:true }
//y=24 z=13 所以返回的是5+24+13
說(shuō)說(shuō)for of與Generator的關(guān)系吧

有一點(diǎn)需要注意的是當(dāng)next方法中返回done為true則終止循環(huán)且不包含該返回對(duì)象,所以上面代碼的return語(yǔ)句返回的6,不包括在for...of循環(huán)之中

function *foo() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
  return 6;
}

for (let v of foo()) {
  console.log(v);
}
Generator中的throw方法

Generator 函數(shù)返回的遍歷器對(duì)象,都有一個(gè)throw方法,可以在函數(shù)體外拋出錯(cuò)誤,然后在 Generator 函數(shù)體內(nèi)捕獲,throw方法可以接受一個(gè)參數(shù),該參數(shù)會(huì)被catch語(yǔ)句接收

var g = function* () {
  try {
    yield;
  } catch (e) {
    console.log(e);
  }
};

var i = g();
i.next();
i.throw(new Error("出錯(cuò)了!"));
// Error: 出錯(cuò)了!(…)

throw方法被捕獲以后,會(huì)附帶執(zhí)行下一條yield表達(dá)式。也就是說(shuō),會(huì)附帶執(zhí)行一次next方法。

var gen = function* gen(){
  try {
    yield console.log("a");
  } catch (e) {
    // ...
  }
  yield console.log("b");
  yield console.log("c");
}

var g = gen();
g.next() // a
g.throw() // b
g.next() // c

Generator中的throw有什么優(yōu)勢(shì)呢?多個(gè)yield表達(dá)式,可以只用一個(gè)try...catch代碼塊來(lái)捕獲錯(cuò)誤,大大方便了對(duì)錯(cuò)誤的處理。

一旦 Generator 執(zhí)行過(guò)程中拋出錯(cuò)誤,且沒(méi)有被內(nèi)部捕獲,就不會(huì)再執(zhí)行下去了

function* g() {
  yield 1;
  console.log("throwing an exception");
  throw new Error("generator broke!");
  yield 2;
  yield 3;
}

如上所示代碼:因?yàn)閽伋隽水惓enerator broke,所以后面的2 3都不會(huì)返回

Generator return
function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

var g = gen();

g.next()        // { value: 1, done: false }
g.return("foo") // { value: "foo", done: true }
g.next()        // { value: undefined, done: true }

g調(diào)用return方法后,返回值的value屬性就是return方法的參數(shù)foo。并且,Generator函數(shù)的遍歷就終止了,返回值的done屬性為true,以后再調(diào)用next方法,done屬性總是返回true

另外一個(gè)特殊情況: Generator 函數(shù)內(nèi)部有try...finally代碼塊,那么return方法會(huì)推遲到finally代碼塊執(zhí)行完再執(zhí)行。也就是說(shuō):調(diào)用return方法后,就開始執(zhí)行finally代碼塊,然后等到finally代碼塊執(zhí)行完,再執(zhí)行return方法

function* numbers () {
  yield 1;
  try {
    yield 2;
    yield 3;
  } finally {
    yield 4;
    yield 5;
  }
  yield 6;
}
var g = numbers();
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.return(7) // { value: 4, done: false }
g.next() // { value: 5, done: false }
g.next() // { value: 7, done: true }
yield*表達(dá)式

yield表達(dá)式后面跟的是一個(gè)遍歷器對(duì)象,需要在yield表達(dá)式后面加上星號(hào),表明它返回的是一個(gè)遍歷器對(duì)象。這被稱為yield*表達(dá)式

let delegatedIterator = (function* () {
  yield "Hello!";
  yield "Bye!";
}());

let delegatingIterator = (function* () {
  yield "Greetings!";
  yield* delegatedIterator;
  yield "Ok, bye.";
}());

for(let value of delegatingIterator) {
  console.log(value);
}
// "Greetings!
// "Hello!"
// "Bye!"
// "Ok, bye."
Generator函數(shù)中的this

Generator函數(shù)不能跟new命令一起用
怎樣讓Generator 函數(shù)返回一個(gè)正常的對(duì)象實(shí)例,既可以用next方法,又可以獲得正常的this?

function* F() {
  this.a = 1;
  yield this.b = 2;
  yield this.c = 3;
}
//這是第一種方式
var obj = {};
var f = F.call(obj);//讓F內(nèi)部的this對(duì)象綁定obj對(duì)象

//第二種方式
var f = F.call(F.prototype);

f.next();  // Object {value: 2, done: false}
f.next();  // Object {value: 3, done: false}
f.next();  // Object {value: undefined, done: true}

obj.a // 1
obj.b // 2
obj.c // 3

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/112241.html

相關(guān)文章

  • ES6 Iterator&Generator

    摘要:可迭代對(duì)象就具有屬性,它是一種與迭代器密切相關(guān)的對(duì)象。它通過(guò)指定的函數(shù)可以返回一個(gè)作用于附屬對(duì)象的迭代器。迭代器特點(diǎn)每次調(diào)用方法時(shí),返回一個(gè)數(shù)組,數(shù)組中兩個(gè)元素,分別表示鍵和值。示例之輸出輸出輸出之迭代器特點(diǎn)返回集合中存在的每一個(gè)鍵。 Iterator由來(lái) 不推薦Iterator方法。 Iterator 函數(shù)是一個(gè) SpiderMonkey 專有特性,并且會(huì)在某一時(shí)刻被刪除。有一點(diǎn),需...

    xietao3 評(píng)論0 收藏0
  • ES6Iterator、Generator

    摘要:舉個(gè)例子遍歷器生成函數(shù),作用就是返回一個(gè)遍歷器對(duì)象,方法返回一個(gè)對(duì)象,表示當(dāng)前數(shù)據(jù)成員的信息。該對(duì)象本身也具有屬性,執(zhí)行后返回自身。 Iterator的作用 一是為各種數(shù)據(jù)結(jié)構(gòu),提供一個(gè)統(tǒng)一的、簡(jiǎn)便的訪問(wèn)接口;(統(tǒng)一)二是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列;(按序)三是ES6創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator接口主要供for...of消費(fèi)。舉個(gè)例子:遍歷器生...

    tuomao 評(píng)論0 收藏0
  • es6 generator函數(shù)

    摘要:返回的遍歷器對(duì)象可以依次遍歷函數(shù)內(nèi)部的每一個(gè)狀態(tài)。示例內(nèi)部捕獲外部捕獲內(nèi)部捕獲外部捕獲上面代碼遍歷器對(duì)象連續(xù)拋出兩個(gè)錯(cuò)誤,第一個(gè)被函數(shù)體內(nèi)的捕獲。上面代碼中,首先執(zhí)行函數(shù),獲取遍歷器對(duì)象,然后使用方法第二行,執(zhí)行異步任務(wù)的第一階段。 參考 來(lái)源《ecmascript6 入門》generator部分 認(rèn)識(shí)generator函數(shù) 形式上,generator函數(shù)有兩個(gè)特點(diǎn):一是functio...

    voidking 評(píng)論0 收藏0
  • ES6系列---迭代器(Iterator)與生成器(Generator

    摘要:迭代器的出現(xiàn)旨在消除這種復(fù)雜性并減少循環(huán)中的錯(cuò)誤。返回一個(gè)迭代器,其值為集合的值。在迭代器中拋出錯(cuò)誤除了給迭代器傳遞數(shù)據(jù)外,還可以給它傳遞錯(cuò)誤條件。通過(guò)方法,當(dāng)?shù)骰謴?fù)執(zhí)行時(shí)可令其拋出一個(gè)錯(cuò)誤。 循環(huán)語(yǔ)句的問(wèn)題 var colors = [red, green, blue]; for(var i=0; i= items.length); var value =...

    DrizzleX 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<