這篇文章帶給大家的內容是關於JavaScript中創建和填充任意長度的陣列方法介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
創建數組的最佳方法是透過字面方式:
const arr = [0,0,0];
不過這並不是長久之計,例如當我們需要創建大型數組時。這篇文章探討了在這種情況下該怎麼做。
沒有空洞的陣列往往表現得更好
在大多數程式語言中,陣列是連續的值序列。在 JavaScript 中,Array 是一個將索引對應到元素的字典。它可以存在空洞(holes) —— 零和陣列長度之間的索引沒有映射到元素(「缺失索引」)。例如,下面的 Array 在索引 1 處有一個空洞:
> Object.keys(['a',, 'c']) [ '0', '2' ]
沒有空洞的陣列也稱為 dense 或 packed。密集數組往往表現更好,因為它們可以連續儲存(內部)。一旦出現了空洞,內部表示就必須改變。我們有兩種選擇:
字典。查找時會消耗更多時間,而且儲存開銷更大。
連續的資料結構,對空洞進行標記。然後檢查對應的值是否是一個空洞,這也需要額外的時間。
不管是哪一種情況,如果引擎遇到一個空洞,它不能只回傳undefined
,它必須遍歷原型鏈並蒐索一個名稱為「空洞索引”的屬性,這需要花費更多時間。
在某些引擎中,例如V8,如果切換到效能較低的資料結構,這種改變將會是永久性的。即使所有空洞都被填補,它們也不會再切換回來了。
關於 V8 是如何表示陣列的,請參閱Mathias Bynens的文章「V8中的元素類型」。
Array
建構子#如果要建立具有給定長度的Array,常用的方法是使用Array
建構子:
const LEN = 3; const arr = new Array(LEN); assert.equal(arr.length, LEN); // arr only has holes in it assert.deepEqual(Object.keys(arr), []);
這種方法很方便,但有兩個缺點:
即使你稍後再用值把陣列完全填滿,這種空洞也會使這個Array 略微變慢。
空洞的預設值一般不會是元素的初始「值」。常見的預設值是零。
Array
建構子後面加上.fill()
方法##.fill()方法會更改目前的Array 並使用指定的值去填充它。這有助於在用
new Array() 建立陣列後對其進行初始化:
const LEN = 3; const arr = new Array(LEN).fill(0); assert.deepEqual(arr, [0, 0, 0]);
警告:如果你用物件作為參數去. fill() 一個數組,所有元素都會引用同一個實例(也就是這個物件沒有被克隆多份):
const LEN = 3; const obj = {}; const arr = new Array(LEN).fill(obj); assert.deepEqual(arr, [{}, {}, {}]); obj.prop = true; assert.deepEqual(arr, [ {prop:true}, {prop:true}, {prop:true} ]);稍後我們會遇到的一種填充方法(
Array.from() )則沒有這個問題。
方法
const LEN = 3; const arr = []; for (let i=0; i < LEN; i++) { arr.push(0); } assert.deepEqual(arr, [0, 0, 0]);
建立 陣列的速度比較慢,因為引擎可能需要隨著陣列的成長多次重新分配連續的記憶體。
使用 填滿陣列
Array.from() 將iterables 和類似陣列的值轉換為Arrays ,它將空洞視為
undefined 元素。這樣可以用它將每個空洞轉換為
undefined:
> Array.from({length: 3}) [ undefined, undefined, undefined ]參數
{length:3} 是長度為3 的類似Array 的對象,其中只包含空洞。也可以使用
new Array(3),但這樣一般會建立更大的物件。
下面這種方式僅適用於可迭代的值,並且與
Array.from()具有類似的效果:
> [...new Array(3)] [ undefined, undefined, undefined ]不過
Array.from()透過
new Array() 來建立它的結果,所以你得到的仍然是一個稀疏數組。
進行映射
Array.from() 進行映射。
> Array.from({length: 3}, () => 0) [ 0, 0, 0 ]
> Array.from({length: 3}, () => ({})) [ {}, {}, {} ]
> Array.from({length: 3}, (x, i) => i) [ 0, 1, 2 ]
> const START=2, END=5; > Array.from({length: END-START}, (x, i) => i+START) [ 2, 3, 4 ]
.keys(),它也將空洞看作是
undefined 元素:
> [...new Array(3).keys()] [ 0, 1, 2 ]
.keys()傳回一個可迭代的序列。我們將其展開並轉換為數組。
undefined填入:
new Array(3 )→
[ , , ,]
Array.from({length: 2})
→ [undefined, undefined]
[...new Array(2)]
→ [undefined, undefined]
填充任意值:
const a=[]; for (let i=0; i<3; i++) a.push(0);
→ [0, 0, 0]
new Array(3).fill(0)
→ [0, 0, 0]
Array.from({length: 3}, () => ({}))
→ [{}, {}, {}]
(唯一对象)
用整数范围填充:
Array.from({length: 3}, (x, i) => i)
→ [0, 1, 2]
const START=2, END=5; Array.from({length: END-START}, (x, i) => i+START)
→ [2, 3, 4]
[...new Array(3).keys()]
→ [0, 1, 2]
我更喜欢下面的方法。我的侧重点是可读性,而不是性能。
你是否需要创建一个空的数组,以后将会完全填充?
new Array(LEN)
你需要创建一个用原始值初始化的数组吗?
new Array(LEN).fill(0)
你需要创建一个用对象初始化的数组吗?
Array.from({length: LEN}, () => ({}))
你需要创建一系列整数吗?
Array.from({length: END-START}, (x, i) => i+START)
如果你正在处理整数或浮点数的数组,请考虑Typed Arrays —— 它就是为这个目的而设计的。它们不能存在空洞,并且总是用零进行初始化。
对于大多数情况,我不会过分担心性能。即使是带空洞的数组也很快。使代码易于理解更有意义。
另外引擎优化的方式和位置也会发生变化。今天最快的方案可能明天就不是了。
以上是JavaScript中建立和填入任意長度的陣列方法介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!