【深度長文】JavaScript陣列所有API全解密
目錄
此文轉載自louis blog
本文先佔坑
,主要是想總結一下知識點,鞏固自己的基礎,程式碼都會自己本地先跑通,也會加上一些自己的理解和補充
陣列是一種非常重要的資料型別,語法簡單、靈活、高效。在多數程式語言中,陣列都充當著至關重要的角色,以至於很難想象沒有陣列的程式語言會是什麼模樣。特別是JavaScript,
它天生的靈活性,又進一步發揮了陣列的特長,豐富了陣列的使用場景。可以豪不誇張地說,不深入地瞭解陣列,不足以寫JavaScript。
截止ES7規範,陣列共包含33個標準的API方法和一個非標準的API方法,使用場景和使用方案紛繁複雜,其中有不少淺坑、深坑、甚至神坑。下面將從Array構造器及ES6新特性開始,逐步幫助你掌握陣列。
Array建構函式
Array構造器用於創造一個新的陣列。通常,我們推薦使用物件字面量建立陣列,這是一個好習慣,但是總有物件字面量乏力的時候,
比如我想建立一個長度為8的空陣列,請看下面兩種方式
// 使用Array構造器
let a = Array(8); // [ <8 empty items> ]
// 使用物件字面量
let b = [];
b.length = 8; // [ <8 empty items> ]
Array構造器明顯要簡潔一些。
如上,我使用了Array(8)
,而不是new Array(8)
,這會有影響嗎?實際上並沒有影響,這得益於Array構造器內部對this指標的判斷,規範內部做了如下處理
When Array is called as a function rather than as a constructor, it creates and initialises a new Array object. Thus the function call Array(…) is
equivalent to the object creation expression new Array(…) with the same arguments.
翻譯一下
當將Array呼叫為函式而不是建構函式時,它將建立並初始化一個新的Array物件。 因此,函式呼叫Array(…)等效於具有相同引數的物件建立表示式new Array(…)。
function Array(){
// 如果this不是Array的例項,那就重新new一個例項
if(!(this instanceof arguments.callee)){
return new arguments.callee();
}
}
下面介紹Array建構函式的介紹,建構函式根據引數長度的不同,有如下兩種不同的處理:
- new Array(arg1,arg2,...),引數長度為0時,返回空陣列,長度大於等於2時,傳入的引數將按照順序依次成為新陣列的第0-N項。
let a = Array(); // []
let b = Array(1,2,3) // []
- new Array(len),當len不是數值時,處理同上,返回一個只包含len元素一項的陣列;當len為數值時,根據如下規範,len最大不能超過32位無符號整型,
即需要小於2的32次方(len最大為Math.pow(2,32)-1
或-1>>>0
),否則將丟擲RangeError。
If the argument len is a Number and ToUint32(len) is equal to len, then the length property of the newly constructed object is set to ToUint32(len).
If the argument len is a Number and ToUint32(len) is not equal to len, a RangeError exception is thrown.
翻譯一下:
如果引數len是Number並且ToUint32(len)等於len,則新構造物件的length屬性將設定為ToUint32(len)。 如果引數len是Number並且ToUint32(len)不等於len,則會引發RangeError異常。
let a = Array('hello'); // ['hello']
let b = Array(3); // [<3 empty items>]
let c = Array(Math.pow(2,32)) // RangeError: Invalid array length
let d = Array(-1 >>> 0) // RangeError: Invalid array length
這裡補充一個js右移>>>
的知識點,可以參考js >>> 0 談談 js 中的位運算
或者MDN按位操作符學習一下
以上,請注意Array構造器對於單個數值引數的特殊處理,如果僅僅需要使用陣列包裹?若干引數,不妨試試使用Array.of
ES6新增的建構函式方法
鑑於陣列的常用性,ES6專門擴充套件了陣列構造器Array,新增了兩個方法: Array.of
,Array.from
。下面看看怎麼使用
Array.of
Array.of用於將引數依次轉化為陣列中的一項,然後返回這個新陣列,而不管這個引數是數字還是其它。它基本上與Array構造器功能一致,唯一的區別就在單個數字引數的處理上。如下:
Array.of(8.0); // [8]
Array(8.0); // [empty × 8]
引數為多個,或單個引數不是數字時,Array.of 與 Array構造器等同。
Array.of(8.0, 5); // [8, 5]
Array(8.0, 5); // [8, 5]
Array.of('8'); // ["8"]
Array('8'); // ["8"]
因此,若是需要使用陣列包裹元素,推薦優先使用Array.of方法。
目前,以下版本瀏覽器提供了對Array.of的支援。
Chrome | Firefox | Edge | Safari |
---|---|---|---|
45+ | 25+ | ✔️ | 9.0+ |
即使其他版本瀏覽器不支援也不必擔心,由於Array.of與Array構造器的這種高度相似性,實現一個polyfill十分簡單。如下:
if (!Array.of){
Array.of = function(){
return Array.prototype.slice.call(arguments);
};
}