前端Tips#2 - 將 arguments 轉換成Array的最佳實踐

本文同步自 JSCON簡時空 - 技術博客,點擊閱讀

視頻講解

【因視頻無法在本文播放,可前往 技術博客原文 查閱】

文字講解

1、先講結論

有很多種方式將 arguments 轉換成數組,那麼哪一種方式是最優的?

爲節約大夥兒的時間,這裏先說一下結論:如果你想將 arguments 轉換成數組,最好的方式是使用 rest 參數轉換的方式(即使用 ... spread 操作符),比如:

function test(…args) {
   console.log(args)
}
test(1,2,3); // [1,2,3]

原因是:性能是 最優 的,可讀性也挺好。

想知道爲什麼的話,可以繼續往下看。

2、原因分析

arguments 對象是所有(非箭頭)函數中都可用的局部變量,它是一個 “Array-Like” 對象,即 “像數組的對象”的意思,有些文章中也會翻譯成 “僞數組對象”。(可以按索引取值、具有 length 屬性,但不一定具備 pushconcat 等數組方法,具體可參考文章僞數組(ArrayLike)內容)

!> 注意:箭頭函數中並不存在 arguments 對象

本期 tip 並不去詳細講 arguments 對象的知識內容(具體知識內容可閱讀本講末尾的參考文章),本講着重講解把它轉換成數組時的最佳實踐。

瀏覽了許多技術文章,將 arguments 對象轉換成數組基本是 4 種方式:

  1. 使用 Array.prototype.slice.call(arguments)進行轉換,或者是使用等效方法 [].slice.call(arguments);
  2. 使用 Array.from(arguments) 進行轉換
  3. 使用 for 循環挨個將 arguments 對象中的內容複製給新數組中
  4. 利用 ES6 中的 rest 參數轉換,let a = (...args) => args;

大多數文章也僅僅是講到這裏爲止,並沒有繼續討論以上哪種方式最優。

接下來我們就用基準測試(Benchmark)的方式來量化上述那種方式性能更好。

3、性能測試

在《做好準備:新的V8即將發佈,Node 的性能正在改變》文中給了結論:

result

我將這文中提及的測試代碼扔到 jsPerf 網站上(測試地址:https://jsperf.com/rest-arguments-slice ),運行結果如下:

benchmark result

圖中數值越高代表性能越好,以上兩幅圖所反映的結果是一致的:

  1. 利用 ES6 中的 rest 參數轉換性能最好
  2. 其次使用 for 循環方式轉換
  3. [].slice 的方式性能較弱
  4. 最差的就是用 Array.from 進行轉換

也可本地進行性能測試,測試代碼在 這兒 獲取;源碼來自 官方提供的 benchmark 示例

因此,如果你想要將 arguments 轉換成數組,那麼毫無疑問應當使用 ES6 中的 rest 參數轉換方式。

除了性能更好之外,rest 參數的用法相對於直接使用 arguments 還有如下優點:

  1. 箭頭函數和普通函數都可以使用。
  2. 更加靈活,接收參數的數量完全自定義。
  3. 可讀性更好,參數都是在函數括號中定義的,不會突然出現一個arguments,顯得很突兀。

4、Q & A

在這裏我簡單解答一些常見的疑惑:

Q: 爲什麼需要將 arguments 對象轉換成數組?

A: 答案也簡單,因爲 Array 實例提供了很多數組方法,比如 .push.concat 等,提供了更多數據操作方式,歸根到底,轉換成數組就是爲了方便操作數據。

Q: 既然經常要將 arguments 轉換成數組,爲什麼最初不把 arguments 設計成數組格式呢?

A: 按照文章 《JavaScript arguments 對象全面介紹》所言, arguments 在語言的早期就引入了,當時的 Array 對象具有 4 個方法: toStringjoinreversesortarguments 繼承於 Object 的很大原因是不需要這四個方法。(當時設計的人也不知道後續的發展會對 arguments 有這方面的強需求…變化無處不在…)

Q: 爲什麼需要 Array-Like 對象(僞數組對象)的存在?

A: 前面說了,轉換成數組也是爲了提供更多數據操作方式;其實 Array-Like 對象的存在,也是爲了給數據提供更多的操作的可能,因爲可以在對象上掛載很多 自定義 的操作方法,使用起來靈活度會很高。

Q: 上述討論的數組轉換結果,是否也適應於其他 “僞數組對象”?

A: 因爲 arguments 也是“僞數組對象”,不難推而廣之,上面討論的數組轉換的方式都可以應用在“僞數組對象”上;至於每個轉換方法的性能如何,我因爲沒有單獨去測試過,所以也不能妄下定論,大家可以自己寫 benchmark 去測試一下(個人猜測應該結論也差不多)。

5、參考文章


關於 “前端Tips專欄”

前端Tips”專欄,隸屬於是 JSCON 專欄系列,設計初衷是快速獲取前端小技巧知識,取材廣泛,涵蓋前端編程諸多領域。設計初衷是快速消費類知識,所以每個 tips 閱讀耗時大約 5 分鐘。爲方便讀者在不同場合閱讀,每篇 tips 配有視頻音頻文字,挑自己喜歡方便的就行。

有兩種方式獲取歷史 tips:

① 在公衆號內回 "tips" “期號” 就可以。例如:回覆 “tips25” 即可獲取第25期 tips
② 前往網站:**https://boycgit.github.io/fe-program-tips,**裏面提供了搜索功能

歡迎大家關注我的知識專欄,更多內容等你來挖掘

個人微信公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章