迭代器和生成器

一.迭代器

1.迭代器是帶有特殊接口的對象,返回一個next方法佣谐,該方法中同時又valuedone屬性,當(dāng)再沒有值可以迭代時,valueundefined方妖,donetrue台谍,否則value為當(dāng)前值,donefalse

2.根據(jù)上面的描述實(shí)現(xiàn)一個迭代器,如下:

let iterator = {
    i: 0,
    items: [2, 4, 6],
    next() {
        let value, done;
        done = (this.i === this.items.length);
        value = done ? undefined : this.items[this.i++];
        return {
            value: value,
            done: done
        }
    }
};
console.log(iterator.next());  //{value: 2, done: false}
console.log(iterator.next());  //{value: 4, done: false}
console.log(iterator.next());  //{value: 6, done: false}
console.log(iterator.next());  //{value: undefined, done: true}

二.生成器

1.生成器是返回迭代器的函數(shù)趁蕊,如下:

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

2.生成器有幾點(diǎn)要注意的:

  • 當(dāng)執(zhí)行流遇到y(tǒng)ield語句時,該生成器就停止運(yùn)轉(zhuǎn)了仔役,直到迭代器再次調(diào)用next
  • 可以再for循環(huán)中使用yield
  • yield只能用在生成器的內(nèi)部掷伙,即使是生成器內(nèi)部的函數(shù)也不行,即:yield無法跨越函數(shù)邊界
  • 無法使用箭頭函數(shù)創(chuàng)建生成器
  • 生成器可以存在于對象的屬性中

三.for-of循環(huán)

1.可迭代類型:指那些包含Symbol.iterator屬性的對象又兵,該屬性定義了返回迭代器的函數(shù)(如:數(shù)組任柜,set,map等)

2.for-of循環(huán)可以循環(huán)可迭代類型沛厨,for-of循環(huán)會在可迭代類型每次執(zhí)行后調(diào)用next()并將結(jié)果存儲在變量中宙地,循環(huán)會持續(xù)進(jìn)行,直到結(jié)果對象的done屬性為true

3.for-of循環(huán)會調(diào)用數(shù)組的Symbol.iterator屬性來獲取迭代器(該方法由幕后的js引擎調(diào)用)逆皮,并將調(diào)用iterator.next()宅粥,并將該結(jié)果對象的value屬性的值賦給num,直到done為true电谣,循環(huán)會退出秽梅,num不會被賦給undefined,代碼如下:

let values = [1, 2, 3];
for (let item of values) {
    console.log(item);   //1 2 3
}

4.對于非可迭代對象剿牺,如nullundefined企垦,使用for-of循環(huán)會拋出錯誤

5.可以在for-of循環(huán)中使用解構(gòu)

let map = new Map();
map.set('name', 'sxt');
map.set('age', 2);
for(let [key, value] of map) {
    console.log(key + " = " + value);
}
//輸出:
//name = sxt
//age = 2

6.for-of循環(huán)可以用于循環(huán)NodeList

四.Symbol.iterator

1.可以用Symbol.iterator屬性來訪問對象默認(rèn)的迭代器,如:

let arr = [6, 7, 8];
let iterator = arr[Symbol.iterator]();
console.log(iterator.next());  //{value: 6, done: false}
console.log(iterator.next());  //{value: 7, done: false}
console.log(iterator.next());  //{value: 8, done: false}
console.log(iterator.next());  //{value: undefined, done: true}

2.判斷一個對象是否可以迭代晒来,可以通過判斷Symbol.iterator屬性是否是一個函數(shù)來實(shí)現(xiàn)钞诡,如:

function isIterator(obj) {
    return typeof obj[Symbol.iterator] === 'function';
}

let arr = [1, 3, 4];
let num = 1;
console.log(isIterator(arr)); //true
console.log(isIterator(num)); //false

3.創(chuàng)建可迭代類型: 我們自己定義的對象默認(rèn)是不可迭代類型,但是我們可以通過設(shè)置Symbol.iterator屬性來使這個對象可以迭代湃崩。因?yàn)榍懊娴?點(diǎn)有講到荧降,判斷一個對象是否可以迭代,其實(shí)是通過Symbol.iterator屬性來確定的竹习,由此可以創(chuàng)建下面的對象

let obj = {
    *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
    }
};
for (let item of obj) {
    console.log(item);  //1 2 3
}

五.內(nèi)置迭代器

1.我們平常迭代數(shù)組誊抛,set和map時,能拿到迭代的值整陌,是因?yàn)檫@些集合中有內(nèi)置的迭代器拗窃,如

let arr = [1, 3, 5];
let set = new Set();
set.add('time');
set.add('user');
set.add('family');
let map = new Map();
map.set('name', 'sxt');
map.set('age', 12);
map.set('sister', 'andy');

for(let item of arr) {
    console.log(item);  // 1 3 5
}
for(let item of set) {
    console.log(item); //time user family
}
for(let item of map) {
    console.log(item); //["name", "sxt"]  ["age", 12] ["sister", "andy"]
}

2.內(nèi)置迭代器分為三種

  • entries()
  • keys()
  • values()

3.數(shù)組的entries返回的是[索引,值]泌辫,set的entries是[值随夸,值],因?yàn)閟et的鍵值是一樣的震放,map的entries是[鍵名宾毒,鍵值],如:

let arr = [1, 3, 5];
let set = new Set();
set.add('time');
set.add('user');
set.add('family');
let map = new Map();
map.set('name', 'sxt');
map.set('age', 12);
map.set('sister', 'andy');

for(let item of arr.entries()) {
    console.log(item);  // [0, 1]  [1, 3]  [2, 5]
}
for(let item of set.entries()) {
    console.log(item); //["time", "time"]  ["user", "user"] ["family", "family"]
}
for(let item of map.entries()) {
    console.log(item); //["name", "sxt"]  ["age", 12] ["sister", "andy"]
}

4.數(shù)組的keys返回的索引殿遂,set的keys返回的還是值诈铛,map的keys返回的是值
5.數(shù)組乙各,set,map的values返回的都是值

六.向迭代器中傳遞參數(shù)

1.我們可以向迭代器中傳遞參數(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.next(5));  //{value: 8, done: false}
console.log(iterator.next());   //{value: undefined, done: true}
  • 這里的難點(diǎn)是理解右側(cè)的代碼會和左邊的中斷
  • 首次調(diào)用next的時候幢竹,不管傳入什么參數(shù)都會被忽略耳峦,因?yàn)閭魅氲膮?shù)會作為yield語句的返回值,而第一次只是yield 1焕毫,而沒有變量

七.包含return語句的生成器

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

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

  • return會讓它提前執(zhí)行完畢并針對next的調(diào)用返回一個值

八.生成器代理

1.即蹲坷,在一個生成器中調(diào)用另外的生成器,有時候邑飒,這樣的操作會更加的實(shí)用

function *create1() {
    yield 1;
    yield 2;
    yield 3;
}

function *create() {
    yield *create1();
    yield true;
}


let iterator = create();
console.log(iterator.next());  //{value: 1, done: false}
console.log(iterator.next());  //{value: 2, done: false}
console.log(iterator.next());  //{value: 3, done: false}
console.log(iterator.next());  //{value: true, done: false}
console.log(iterator.next());  //{value: undefined, done: true}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末循签,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疙咸,更是在濱河造成了極大的恐慌县匠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件罕扎,死亡現(xiàn)場離奇詭異聚唐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)腔召,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門杆查,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人臀蛛,你說我怎么就攤上這事亲桦。” “怎么了浊仆?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵客峭,是天一觀的道長。 經(jīng)常有香客問我抡柿,道長舔琅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任洲劣,我火速辦了婚禮备蚓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘囱稽。我一直安慰自己郊尝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布战惊。 她就那樣靜靜地躺著流昏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上况凉,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天谚鄙,我揣著相機(jī)與錄音,去河邊找鬼刁绒。 笑死襟锐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的膛锭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼蚊荣,長吁一口氣:“原來是場噩夢啊……” “哼初狰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起互例,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤奢入,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后媳叨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腥光,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年糊秆,在試婚紗的時候發(fā)現(xiàn)自己被綠了武福。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡痘番,死狀恐怖捉片,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情汞舱,我是刑警寧澤伍纫,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站昂芜,受9級特大地震影響莹规,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜泌神,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一良漱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧腻扇,春花似錦债热、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春墙杯,著一層夾襖步出監(jiān)牢的瞬間配并,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工高镐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溉旋,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓嫉髓,卻偏偏與公主長得像观腊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子算行,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容