国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

ECMAScript 6集合遍歷機制分析

2021-03-10 09:20:22張曉靜
電子技術(shù)與軟件工程 2021年20期
關(guān)鍵詞:數(shù)據(jù)結(jié)構(gòu)調(diào)用內(nèi)置

張曉靜

(92981 部隊 北京市 100161)

ECMAScript 是 通 過Ecma 國 際(Ecma International, 前身為歐洲計算機制造商協(xié)會,European computer manufacturers association)制訂的ECMA-262 協(xié)議標準化的腳本程序設(shè)計語言[1],JavaScript 的語法和語義是ECMAScript 規(guī)范的實現(xiàn)。自1997年起至今ECMAScript 不斷更新并發(fā)布了多個版本。2011年ECMAScript 5.1 版本(ES5)成為了ISO 國際標準(ISO/IEX 16262),并在萬維網(wǎng)上得到廣泛應(yīng)用。2015年ECMAScript 6 版本(ES6)是繼ES5 之后的一次重大改進,旨在讓JavaScript 成為企業(yè)級開發(fā)語言而不再局限于瀏覽器端,而后發(fā)布的版本都是在ES6 的基礎(chǔ)上新增較少特性。ES6 經(jīng)迅速普及,目前基本已成為業(yè)界標準。

遍歷是一種循環(huán)裝置,能夠順序訪問集合中每一個元素。編程語言往往通過提供一種機制來支持遍歷集合,將內(nèi)部實現(xiàn)細節(jié)隱藏在類的私有部分[2],開發(fā)人員只需調(diào)用公共方法,而對于架構(gòu)師級別的開發(fā)人員來說,了解底層實現(xiàn)是必要的。本文旨在通過剖析ES6 遍歷機制的內(nèi)部實現(xiàn)細節(jié),來為深入理解ES6 語言設(shè)計思路和未來工作提供堅實的理論基礎(chǔ)。

1 遍歷語句和方法

1.1 遍歷語句對比分析

遍歷語句通常在大括號內(nèi)部寫入每次循環(huán)需要做什么,通過continue、break 語句改變遍歷正常進行過程。ES5 中集合主要是Array(數(shù)組)和Object(對象),遍歷語句主要有for、while、dowhile 及for-in,表1 為ES5 及ES6 的遍歷語句對比分析。

表1:遍歷語句對比

for 需要規(guī)定指針賦值語句、執(zhí)行條件表達式和計數(shù)器更新表達式,如果是多層嵌套循環(huán),則每一層都需要這些表達式或語句。for、while、do-while 語句是最傳統(tǒng)和簡易的遍歷語句,底層處理功能較少,語法相對繁瑣,但這樣詳細的控制方式使得輸出方式更靈活。

for-in 語句遍歷輸出對象的可枚舉屬性,包括其自身屬性和原型鏈上繼承的屬性,所有屬性都會轉(zhuǎn)換為字符串輸出。其遍歷順序是一個相對復(fù)雜的規(guī)則:首先,遍歷對象自身的可枚舉屬性,如果是非負整數(shù)屬性或能夠轉(zhuǎn)換為非負整數(shù)的字符串屬性,則先按照數(shù)值的升序順序遍歷,接著對不能轉(zhuǎn)換為非負整數(shù)的字符串屬性,按照元素加入對象的順序遍歷;然后,依照上述規(guī)則逐層遍歷對象原型鏈上的可枚舉屬性,直到頂層Object 的可枚舉屬性也遍歷結(jié)束。for-in 的語法較為簡潔,但遍歷順序不是直觀的元素加入順序,且會遍歷原型鏈上的可枚舉屬性,這不一定是開發(fā)人員需要的。圖1為for-in 遍歷對象舉例,輸出結(jié)果順序與上述規(guī)則一致。

圖1:for-in 遍歷對象舉例

ES6 新增集合主要有Set、Map,以及for-of 遍歷語句。for-of語句能夠遍歷任何可遍歷對象,語法和for-in 一樣簡潔,而它輸出順序固定,支持多種輸出形式,是ES6 標準下遍歷的最佳選擇。

1.2 遍歷方法對比分析

傳統(tǒng)ES5 遍歷方法需要傳遞一個回調(diào)函數(shù)作為參數(shù),回調(diào)函數(shù)中寫入每次循環(huán)時需要做什么,并寫入return 語句返回循環(huán)結(jié)果。表2 為ES5 與ES6 的遍歷方法對比分析,ES5 遍歷的方法主要有:forEach、map、filter、some、every;ES6 針對Array 新增了find、findIndex,并對Set、Map、Array 都提供了entries、keys 和values方法。

表2:遍歷方法對比

forEach 方法可以遍歷Set、Map 和Array,回調(diào)函數(shù)內(nèi)return語句代表退出本次循環(huán)而不是中斷遍歷,中斷遍歷需要拋出異常,這是一種不友好的編程風格。map 方法用于映射一個新的數(shù)組,return 語句代表本次循環(huán)元素映射值。some 方法用于查找符合條件的元素, return 語句返回一個布爾值,代表當前元素是否符合條件,找到符合條件的元素時中斷遍歷。ES6 新增的find、findIndex 方法也是用于查找。every 方法用于測試集合元素,return 語句返回一個布爾值,代表是否通過測試,找到測試不通過的元素時中斷遍歷。以上方法使用場景固定,語法相對刻板,且中斷遍歷方式不大友好。

ES6 新增的keys、values、entries 分別是用于遍歷集合元素的鍵名、鍵值、鍵值對,Array、Set、Map 集合都增加了這三個遍歷方法,方法通過實例調(diào)用,不再以傳遞回調(diào)函數(shù)作為參數(shù)的方式調(diào)用。此外,Object 也新增了這三類方法。ES6 新增的遍歷方法從根本上滿足了集合遍歷的需求。

2 ES6遍歷機制

ES6 標準下的集合主要有Array、Object、Set、Map,開發(fā)人員基于實際需求,可能還需要組合使用這些集合,即自定義一個較為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。處理不同的數(shù)據(jù)結(jié)構(gòu),需要一個統(tǒng)一的遍歷接口機制。ES6 新增的Iterator(遍歷器),旨在提供這樣一個統(tǒng)一的機制,這與Java 等后端語言具有相似性。

2.1 遍歷器協(xié)議

一個遍歷器對象應(yīng)包含一個名為next 的方法,而next 方法返回一個具有value、done 兩個屬性值的對象,其中value 為當前集合元素值,done 是代表遍歷是否結(jié)束的布爾值,而返回一個遍歷器對象的方法稱為遍歷器方法,這一規(guī)則稱為遍歷器協(xié)議。遍歷器對象相當于一個指針,在遍歷過程中指向當前循環(huán)的元素,調(diào)用其next 方法則移動指針,直到done 的值為true,代表遍歷結(jié)束。圖2為一個自定義遍歷器方法。

圖2:自定義遍歷器方法

2.2 可遍歷協(xié)議

遍歷器協(xié)議只是規(guī)定了集合遍歷方法的編寫規(guī)則,在此情況下,想要調(diào)用一種集合的遍歷器方法,要知道方法名稱、然后執(zhí)行得到遍歷器對象、再逐步調(diào)用遍歷器對象的next 方法。在集合種類多或自定義數(shù)據(jù)結(jié)構(gòu)的情況下,僅有遍歷器協(xié)議并不足夠。

Iterable(可遍歷)協(xié)議定義了一個默認的遍歷器接口,約定將集合的默認遍歷器方法都部署在該集合原型對象的Symbol.iterator屬性上。當一個數(shù)據(jù)結(jié)構(gòu)具有Symbol.iterator 屬性,則認為它是可遍歷的。其中,Symbol 是ES6 新增的原始數(shù)據(jù)類型,用于表示獨一無二的屬性,Symbol.iterator 是約定作為集合默認遍歷器方法的屬性名稱。Symbol 類型的屬性是可枚舉屬性,但for-in 語句遍歷時排除了這類屬性??杀闅v協(xié)議是ES6 實現(xiàn)統(tǒng)一遍歷機制的核心。

針對一個可遍歷對象,底層執(zhí)行遍歷的過程如下:

(1)調(diào)用該對象Symbol.iterator 屬性的方法,獲取遍歷器對象;

(2)調(diào)用遍歷器對象的next 方法,獲得包含value 和done 的返回值,done 的值為true 則退出循環(huán),否則輸出value 值;

(3)重復(fù)第2 步直到 done 值為true。ES6 中所有支持可遍歷對象的場合,都是按照這一過程執(zhí)行,例如for-of 語句。

2.3 內(nèi)置遍歷機制

2.3.1 數(shù)據(jù)結(jié)構(gòu)的內(nèi)置遍歷器方法

ES6 為一些數(shù)據(jù)結(jié)構(gòu)內(nèi)置了遍歷器方法,數(shù)據(jù)結(jié)構(gòu)主要有String、Array、Set、Map,以及函數(shù)的arguments 參數(shù)類數(shù)組、文檔對象模型的NodeList(節(jié)點列表)類數(shù)組,內(nèi)置遍歷器方法有keys、values 和entries,以及Symbol.iterator,內(nèi)置的遍歷器方法與默認遍歷器方法根據(jù)實際需要可能是同一個方法實例。

圖3 為String 等數(shù)據(jù)結(jié)構(gòu)內(nèi)置遍歷器方法原型鏈。String 類型遍歷時只需要輸出每個字符,因此僅有Symbol.iterator 屬性上部署的默認遍歷器方法。Set 是元素不重復(fù)的類數(shù)組,鍵值與鍵名相同,因此Set 原型的keys 和values 屬性指向同一個內(nèi)置的名為values 的遍歷器方法,通常遍歷Set 集合期望輸出的是元素值,因此values方法還應(yīng)作為默認的遍歷器方法,即Symbol.iterator 屬性也指向values 方法。Array、Map 的遍歷器方法內(nèi)置模式與Set 大致相同,并根據(jù)自身特點分別指定了默認遍歷器方法。這四種數(shù)據(jù)結(jié)構(gòu)都有默認遍歷器方法,因此它們的實例對象都是可遍歷的。

圖3:數(shù)據(jù)結(jié)構(gòu)內(nèi)置遍歷器方法原型鏈

2.3.2 內(nèi)置遍歷器對象的遍歷機制

ES6 針對String 等數(shù)據(jù)結(jié)構(gòu)增加了內(nèi)置遍歷器原型對象,是隱藏在原型鏈內(nèi)部的底層實現(xiàn),內(nèi)置遍歷器對象通過調(diào)用內(nèi)置遍歷器方法生成。ES6 還實現(xiàn)了內(nèi)置遍歷器對象的遍歷機制,使得內(nèi)置遍歷器對象本身也可遍歷。例如,一個數(shù)組實例a,a 是可遍歷的,a.entries()也是可遍歷的。

圖4 為String、Array、Set、Map 四種數(shù)據(jù)結(jié)構(gòu)內(nèi)置遍歷器對象原型鏈??梢钥闯?,ES6 設(shè)置了一個無名對象繼承Object,這個無名對象僅有一個Symbol.iterator 屬性,該屬性對應(yīng)方法的功能只是返回this,即返回對象本身,這四種數(shù)據(jù)結(jié)構(gòu)的遍歷器對象原型都繼承了這個無名對象,同時遍歷器原型本身都有一個next 方法,不同數(shù)據(jù)結(jié)構(gòu)的內(nèi)置遍歷器原型實現(xiàn)不同的next 方法來規(guī)定其元素遍歷順序。

圖4:內(nèi)置遍歷器對象原型鏈

這一機制使得內(nèi)置遍歷器對象遵循了可遍歷協(xié)議,例如,一個數(shù)組實例a,使用for-of 語句遍歷a.entries()時,首先,執(zhí)行a.entries()獲得a 的遍歷器對象aItr;然后,執(zhí)行aItr[Symbol.iterator](),底層調(diào)用時將從aItr 自身出發(fā)在原型鏈上逐層向上查找,最終找到無名對象上的Symbol.iterator 方法,該方法返回this,即執(zhí)行結(jié)果仍為aItr;最后,循環(huán)執(zhí)行aItr.next(),逐個獲取元素值,同樣地,底層調(diào)用next 方法時從自身出發(fā)在原型鏈上向上查找,實際調(diào)用了Array Iterator(數(shù)組遍歷器)原型上的next 方法。

2.4 遍歷體系結(jié)構(gòu)及使用場合

for-of 是可遍歷對象最常見的使用場合,此外還有數(shù)組形式解構(gòu)、擴展運算符、Array.from()方法、Generator(生成器)中的yield*表達式等等。圖5 表達了ES6 遍歷機制的整體結(jié)構(gòu),其中,數(shù)據(jù)結(jié)構(gòu)的內(nèi)置遍歷器方法、遍歷器對象的遍歷方法或自定義對象的遍歷器方法都是通過Symbol.iterator 屬性及其相應(yīng)方法作為接口接入了ES6 遍歷體系,讓數(shù)據(jù)對象、遍歷器對象、自定義對象都成為了可遍歷的對象,于是可以在所有ES6 中支持遍歷的場合被遍歷,這些使用場合都會在底層執(zhí)行2.2 中描述的遍歷執(zhí)行過程。

圖5:ES6 遍歷體系結(jié)構(gòu)圖

3 結(jié)語

相比ES5,ES6 在遍歷方面新增了很多新特性,并通過可遍歷協(xié)議實現(xiàn)了統(tǒng)一遍歷機制,建立起完整的遍歷體系,開發(fā)人員通過對自定義數(shù)據(jù)結(jié)構(gòu)設(shè)置默認遍歷器方法來接入這一體系,實現(xiàn)多場合靈活輸出。生成器對象也是一種遍歷器對象,而生成器對象內(nèi)置遍歷方法的實現(xiàn)方式,以及異步遍歷器的實現(xiàn)細節(jié),可以作為下一步研究內(nèi)容。

猜你喜歡
數(shù)據(jù)結(jié)構(gòu)調(diào)用內(nèi)置
內(nèi)置加勁環(huán)T型管節(jié)點抗沖擊承載力計算
核電項目物項調(diào)用管理的應(yīng)用研究
LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
芯片內(nèi)置測試電路的設(shè)計
電子測試(2018年14期)2018-09-26 06:04:00
基于系統(tǒng)調(diào)用的惡意軟件檢測技術(shù)研究
“翻轉(zhuǎn)課堂”教學模式的探討——以《數(shù)據(jù)結(jié)構(gòu)》課程教學為例
高職高專數(shù)據(jù)結(jié)構(gòu)教學改革探討
中國市場(2016年45期)2016-05-17 05:15:48
內(nèi)置管腸排列術(shù)治療嚴重粘連性腸梗阻的臨床分析
TRIZ理論在“數(shù)據(jù)結(jié)構(gòu)”多媒體教學中的應(yīng)用
《數(shù)據(jù)結(jié)構(gòu)》教學方法創(chuàng)新探討
河南科技(2014年5期)2014-02-27 14:08:57
郑州市| 东兰县| 霍州市| 高青县| 合肥市| 德兴市| 河东区| 彭州市| 翁源县| 浑源县| 庆阳市| 庄河市| 修水县| 安顺市| 杭锦旗| 安阳县| 日土县| 甘肃省| 读书| 霍城县| 民和| 泾阳县| 五峰| 子洲县| 万盛区| 蒙山县| 浦城县| 收藏| 肇庆市| 九台市| 楚雄市| 宁武县| 施秉县| 瓦房店市| 克拉玛依市| 金塔县| 肇源县| 永吉县| 桐庐县| 郓城县| 涟水县|