您好,登錄后才能下訂單哦!
這篇文章主要介紹了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()
)則沒有這個問題。
.push()
方法const LEN = 3; const arr = []; for (let i=0; i < LEN; i++) { arr.push(0); } assert.deepEqual(arr, [0, 0, 0]);
這一次,我們創建并填充了一個數組,同時里面沒有出現漏洞。所以操作這個數組時應該比用構造函數創建的更快。不過 創建 數組的速度比較慢,因為引擎可能需要隨著數組的增長多次重新分配連續的內存。
undefined
填充數組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()
進行映射。
使用小整數創建數組:
> 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中怎么創建和填充任意長度的數組內容對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。