版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
起源
一段標(biāo)準(zhǔn)的for循環(huán)代碼:
varcolors=["red","blue11];
for(vari=O>/e八=colons.length;i</c八;i++){
conso/e」og(co/od[]);
)
看著很簡單,但是再回顧這段代碼,實際上我們僅僅是需要數(shù)組中元素的值,但
是卻需要提前獲取數(shù)組長度,聲明索引變量等,尤其當(dāng)多個循環(huán)嵌套的時候,更
需要使用多個索引變量,代碼的復(fù)雜度就會大大增加,比如我們使用雙重循環(huán)進(jìn)
行去重:
Functionui^ique(array){
varres=[];
for(vari=O,arrayLeia=array.length;i<arrayLM;i++){
for(varj=O,resLe八=八gtk;j<resLen;j++){
if(arrayfi]===resfj]){
break)
}
}
if(j===rcsLc八)(
res.pus^arrayli]');
}
]
匕血巾res;
)
為了消除這種復(fù)雜度以及減少循環(huán)中的錯誤(比如錯誤使用其他循環(huán)中的變量),
ES6提供了迭代器和forof循環(huán)共同解決這個問題。
迭代器
所謂迭代器,其實就是一個具有next()方法的對象,每次調(diào)用next()都會返
回一個結(jié)果對象,該結(jié)果對象有兩個屬性,value表示當(dāng)前的值,done表示遍
歷是否結(jié)束。
我們直接用ES5的語法創(chuàng)建一個迭代器:
fiA八ctioncreateIteratoitems){
vari=O;
return(
Mxt:fuMtioi^O{
vardoM=i>=length;
varvalue=IdoM?辿35口'+":u八defined;
return(
doM:doM,
value:value
};
)
};
)
//iterator就是個迭代器對象item,"=c%比cites亡。?[工2>3]);
cok\$ol^log(iterator.Mxt()');//{doM:false,value:(}coiasole.log(iterator.MXt('))://{doM:
false,value:2}cok\sole.log(iterator.iaext());//{doM:fake,value:
3}coiasole.log(iterator.Mxt(y);//{doM:true,value:〃八de行八cd)
forof
除了迭代器之外,我們還需要一個可以遍歷迭代器對象的方式,ES6提供了for
of語句,我們直接用forof遍歷一下我們上節(jié)生成的遍歷器對象試試:
variterator=cre.atelterator([i-,2,3J);
For(letvalueofiterator){
co^.sole..log(value);
}
結(jié)果報錯TgpeError:iteratorisnotiterab/e,表明我們生成的iterator對象并不是
iterable(可遍歷的)。
那什么才是可遍歷的呢?
其實一種數(shù)據(jù)結(jié)構(gòu)只要部署了Iterator接口,我們就稱這種數(shù)據(jù)結(jié)構(gòu)是"可遍歷
的"(iterable)。
ES6規(guī)定,默認(rèn)的Iterator接口部署在數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator屬性,或
者說,一個數(shù)據(jù)結(jié)構(gòu)只要具有SymboLiterator屬性,就可以認(rèn)為是‘可遍歷的”
(iterable)。
舉個例子:
coMobj={
value:1
);
For(valueofobj){
co^ole.log(value);
]
//TypeError:iteratoris八。titerable
我們直接forof遍歷一個對象,會報錯,然而如果我們給該對象添加
SymboLiterator屬性:
constobj={
value:1
};
obj[Syi^bol.iterator]=Fn八cti。八0(
returncreatetteratordlj2,3]);
for(valueofobj){
co^ole.log(value);
}
//1〃2〃3
由此,我們也可以發(fā)現(xiàn)forof遍歷的其實是對象的SymboLiterator屬性。
默認(rèn)可遍歷對象
然而如果我們直接遍歷一個數(shù)組對象:
coi^stcolors=["red1^"greeia1^"blue"];
for(letcolorofcolors){
conso/e」og(co/oK);
}
//red//g%e"/blue
盡管我們沒有手動添加SymboLiterator屬性,還是可以遍歷成功,這是因為
ES6默認(rèn)部署了SymboLiterator屬性,當(dāng)然我們也可以手動修改這個屬性:
vavcolors=["red","勿
colors[Sykv\bol.iterator]=fu八cti。八0(
returncreatelteratord^j2,3]);
for(letcolorofcolors}{
co八os/e」og(co/or);
)
//1//2〃3
除了數(shù)組之外,還有一些數(shù)據(jù)結(jié)構(gòu)默認(rèn)部署了SymboLiterator屬性。
所以for...of循環(huán)可以使用的范圍包括:
1.數(shù)組
2.Set
3.Map
4.類數(shù)組對象,如arguments對象、DOMNodeList對象
5.Generator對象
6,字符串
模擬實現(xiàn)forof
其實模擬實現(xiàn)forof也比較簡單,基本就是通過Symbol.iterator屬性獲取迭
代器對象,然后使用while遍歷一下:
八ctio八forOf(obj,cb){
letiterable,yesbdt;
if(typeofobj[Sykv\bol.iterator]/=="futaction")
thrownewTypeErrorfresult+“is八。2iterablen);
if(typeofch!==throwMWTgpcE"叭“cbmustbecallable11);
iterable=obj[Sykv\bol.iterator]();
result=iterable.MxtO;
while(frcsult.doM){
cb(result.value);
result=iterable.MXtO;
]
內(nèi)建迭代器
為了更好的訪問對象中的內(nèi)容,比如有的時候我們僅需要數(shù)組中的值,但有的時
候不僅需要使用值還需要使用索引,ES6為數(shù)組、M叩、Set集合內(nèi)建了以下三
種迭代器:
1.entries()返回一個遍歷器對象,用來遍歷[鍵名,鍵值]組成的數(shù)組。對于
數(shù)組,鍵名就是索引值。
2.keys()返回一個遍歷器對象,用來遍歷所有的鍵名。
3.values()返回一個遍歷器對象,用來遍歷所有的鍵值。
以數(shù)組為例:
varcolors-[〃匕力,"gree"一例ue”];
For(letindexofco/od.kcgs。){
co^ole.log(ik\dex);
)
//O//2〃2
for(letcolorofcolors.values()){
co八so/e」og(co/oK);
}
//%d〃grec八〃blue
for(letofco/od.cMricsO){
co八S0/c」og(7±e&);
]
//[O,"red"]//[1,"green"]//[2,"blue,"]
Map類型與數(shù)組類似,但是對于Set類型需要注意以下:
,,U
varcolors=MWSet(["redJ"gree^'jblue"]);
for(letindexofco/od.kcgs。){
co八so/e」og(i八dex);
)
//red//gree八〃blue
for(letcolorofcolors.valu^O){
coi^sole.log(color);
]
//red//gree八〃blue
for(letofCO/OHS.C*也s。){
co八so/e」og(itcd);
)
//[Wed",—"]//["grec八","gwe八"]//["blue11,ub[iAe.u]
Set類型的keys()和valuesQ返回的是相同的迭代器,這也意味著在Set這
種數(shù)據(jù)結(jié)構(gòu)中鍵名與鍵值相同。
而且每個集合類型都有一個默認(rèn)的迭代器,在for-of循環(huán)中,如果沒有顯式指
定則使用默認(rèn)的迭代器。數(shù)組和Set集合的默認(rèn)迭代器是valuesQ方法,Map
集合的默認(rèn)迭代器是entriesQ方法。
這也就是為什么直接forof遍歷Set和M叩數(shù)據(jù)結(jié)構(gòu),會有不同的數(shù)據(jù)結(jié)構(gòu)
返回:
constvaluer=newSet(口,2>3]);
for(letvalueofvalues}{
coi^sole.log(value);
]
//1//2〃3
constvalues=MWMapd^'keyl","value^"^["keg2"JV〃Me2"JD;F"(麻valueofvaliAes){
co^ole.log(value);
}
1,,,,un
//[''keyl',"valued"]//[key2JvalueZ]
遍歷Map數(shù)據(jù)結(jié)構(gòu)的時候可以順便結(jié)合解構(gòu)賦值:
,,,,n
constvaluer=newMap(l[keyl"Jvaluel],["keg2"J"Hue2"JJ);
for(let[key,value]ofvalues}{
con$ol^.log(key+":"+value);
}
//keglvabc工//key2.:value2
Babel是如何編譯forof的
我們可以在Babel的Tryitout中查看編譯的結(jié)果:
,,
coi^stcolors=MWSet(["redJ"blue"]);
for(letcolorofcolors){
coy^ole.log(color);
}
對于這樣一段代碼,編譯的結(jié)果如下:
“usestrict";
varcolors=MWSet(["red","g%e八、%山e〃J);
varJteratorNor^alCoi^pletioia=tru^var^didlteratorError=false;varJteratorError=
undefined;
try(
for(
vavJterator=colorslSyi^bol.iteratorJOj_$tcp;
!(_iteratorMon^alCo^pletioi^=(_$tep=_iterator?.八cx±0).do八e);
JteratorNor^alCokv\pletioki=true.
){
varcolor=_step.value)
co^ole.log(colo^)
}
}catch(err){
_didlteratorEr^or=true;
Jter^torError=err;
}finally{
try(
if(!jteratorNori^alCokv\pletion.&&Jterator.retum){
Jterator.retum();
)
}finally{
if(_didlteratorError){
throwjtemtorHrror;
)
)
)
至少由編譯的結(jié)果可以看出,使用f*of循環(huán)的背后,還是會使用
Symbol.iterator接口。
而這段編譯的代碼稍微復(fù)雜的地方有兩段,一段是for循環(huán)這里:
for(
varJte^ato^=colors[Sy^bol.iterator](),_$tep;
!(JteratorNo^i^alCo^pletioi^=(_$tep=」'±CK〃tor*.八ex±()).do八e);
JteratorNormaiCo^vxpletioia=true
)(
vav-color-_$tep.vatue;
console.log(color);
)
跟標(biāo)準(zhǔn)的for循環(huán)寫法有些差別,我們看下for語句的語法:
for(initialize;test;mcremen.t)statement;
initialize,test和increment三個表達(dá)式之間用分號分割,它們分別負(fù)責(zé)仞始化
操作、循環(huán)條件判斷方口計數(shù)器變量的更新。
for語句其實就相當(dāng)于:
i八itia(ize;whi(e(test){
merecent;
]
代碼的邏輯為:先進(jìn)行初始化,然后每次循環(huán)執(zhí)行之前會執(zhí)行test表達(dá)式,并
判斷表達(dá)式的結(jié)果來決定是否執(zhí)行循環(huán)體,如果test計算結(jié)果為真值,則執(zhí)行
循環(huán)體中的statemento最后,執(zhí)行increment表達(dá)式。
而且值得注意的是,其實for循環(huán)中的三個表達(dá)式中任意一個都可以被忽略,
不過分號還是要寫的。
比如土,不過這就是一個死循環(huán)……
比如:
vari-O,
他八=colors.leiagtk;fo^(;i<他八;i++)(
coi^sole.log(colors[i]);
]
又比如:
vari-
加八=co/。%.3Vg仇For*(;i<加八;){
i++;
)
然后我們再來看Babel編譯的這個for循環(huán)表達(dá)式:
for(
variterator=colorslSyi^bol.iteratorJO,_$tep;
((JteratorNor^,alCoiM.pletioi^=(_$tep=_iterator.MKt(y).doM);
JteratorNori^alCo^pletioi^=true
)(
varcolor=jtepvaliA。;
coi^sole.log(color);
)
用while的寫法相當(dāng)于:
varJte^ator=colors[Syi^bo(.iterator](),
_$tep;while-(!(」七。戊。小"陋址0呻怙七沁八=(_$tep=_iterator.MXt(y).doi^e)){
varcolor=_$tep.va(ue;
co^sole.log(color);
_jteratorNov'w\alCow\pletio^-true;
)
是不是就好懂/很多呢,然后你就會發(fā)現(xiàn),其實亡OHNOKHAHCO叫?/etio八=true這
句是完全沒有必要的……
另外一段稍微復(fù)雜的代碼是:
try(
}catch(err){
}finally(
try(
if(!_iteratorNori^alCoi^pletioi^&&Jterator.retum){
Jterator.retum();
)
}finally{
)
)
因為_iteratorNorkv\alCokv\pletio^.=(jtep=Jterator.MxtO).doM,所以
JteratorNormalCompletion表示的就是是否完成了一次完整的迭代過程,如果
沒有正常的迭代完成,并且迭代器有return方法時,就會執(zhí)行該方法。
而之所以這么做,就要提到迭代器的return方法。
引用阮一峰老師的ECMAScript6入門:
遍歷器對象除了具有next方法,還可以具有return方法和
throw方法。如果你自己寫遍歷器對象生成函數(shù),那么next方法
是必須部署的,return方法和throw方法是否部署是可選的。
return方法的使用場合是,如果for...of循環(huán)提前退出(通常是因
為出錯,或者有break語句或continue語句),就會調(diào)用return
方法。如果一個對象在完成遍歷前,需要清理或釋放資源,就可以
部署return方法。
我們可以舉個例子:
fuMtioiacreateIterator(items){
vari-O\
return{
next:ftmc力'。八0(
vavdoM=i>=iteMS.Ie八gth;
varvalue=IdoM?:u八defined;
return(
doM:doM,
value:value
);
h
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 汽車尾氣檢測中心可行性研究報告
- 南京工業(yè)大學(xué)浦江學(xué)院《汽車美容》2022-2023學(xué)年第一學(xué)期期末試卷
- 《小毛蟲》說課稿
- 南京工業(yè)大學(xué)《中國文明史(中國傳統(tǒng)天文學(xué))》2021-2022學(xué)年第一學(xué)期期末試卷
- 有關(guān)液壓課件教學(xué)課件
- 南京工業(yè)大學(xué)《藥劑學(xué)》2021-2022學(xué)年第一學(xué)期期末試卷
- 南京工業(yè)大學(xué)《數(shù)學(xué)類專業(yè)寫作》2023-2024學(xué)年第一學(xué)期期末試卷
- 南京工業(yè)大學(xué)《深度學(xué)習(xí)》2023-2024學(xué)年期末試卷
- 南京工業(yè)大學(xué)《綠色建筑概論》2022-2023學(xué)年第一學(xué)期期末試卷
- 示范教案(兼顧效率與公平 第二課時)
- 中國兒童嚴(yán)重過敏反應(yīng)診斷與治療建議(2022年)解讀
- 動火作業(yè)安全規(guī)范AQ3022-2008
- Unit 1 Our living planet Reading 課件-2022-2023學(xué)年高中英語牛津譯林版(2020)選修第一冊
- 如何做好談話筆錄演示文稿
- 耐酸泵廠家排名前十耐酸堿泵十大品牌
- 小學(xué)道德與法治人教三上冊安全護(hù)我成長心中的(吳運芝)
- 主通風(fēng)機(jī)司機(jī)巡回檢查制度
- 四川省鄉(xiāng)村機(jī)耕道建設(shè)規(guī)范和技術(shù)標(biāo)準(zhǔn)(試行)
- 娃娃家區(qū)角游戲方案
- 華為SD-WAN高層主打膠片
- 國網(wǎng)基建各專業(yè)考試題庫大全-安全專業(yè)-下(多選、判斷題匯總)
評論
0/150
提交評論