溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript中怎么創(chuàng)建和填充任意長度的數(shù)組

發(fā)布時間:2020-12-03 10:29:57 來源:億速云 閱讀:212 作者:小新 欄目:web開發(fā)

這篇文章主要介紹了JavaScript中怎么創(chuàng)建和填充任意長度的數(shù)組,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

創(chuàng)建數(shù)組的最佳方法是通過字面方式:

const arr = [0,0,0];

不過這并不是長久之計,比如當(dāng)我們需要創(chuàng)建大型數(shù)組時。這篇博文探討了在這種情況下應(yīng)該怎么做。

沒有空洞的數(shù)組往往表現(xiàn)得更好

在大多數(shù)編程語言中,數(shù)組是連續(xù)的值序列。在 JavaScript 中,Array 是一個將索引映射到元素的字典。它可以存在空洞(holes) —— 零和數(shù)組長度之間的索引沒有映射到元素(“缺失索引”)。例如,下面的 Array 在索引 1 處有一個空洞:

> Object.keys(['a',, 'c'])
[ '0', '2' ]

沒有空洞的數(shù)組也稱為 dense  packed。密集數(shù)組往往表現(xiàn)更好,因為它們可以連續(xù)存儲(內(nèi)部)。一旦出現(xiàn)了空洞,內(nèi)部表示就必須改變。我們有兩種選擇:

  • 字典。查找時會消耗更多時間,而且存儲開銷更大。

  • 連續(xù)的數(shù)據(jù)結(jié)構(gòu),對空洞進(jìn)行標(biāo)記。然后檢查對應(yīng)的值是否是一個空洞,這也需要額外的時間。

不管是哪種情況,如果引擎遇到一個空洞,它不能只返回 undefined,它必須遍歷原型鏈并搜索一個名稱為“空洞索引”的屬性,這需要花費更多時間。

在某些引擎中,例如V8,如果切換到性能較低的數(shù)據(jù)結(jié)構(gòu),這種改變將會是永久性的。即使所有空洞都被填補(bǔ),它們也不會再切換回來了。

關(guān)于 V8 是如何表示數(shù)組的,請參閱Mathias Bynens的文章“V8中的元素類型”。

創(chuàng)建數(shù)組

Array 構(gòu)造函數(shù)

如果要創(chuàng)建具有給定長度的 Array,常用的方法是使用 Array 構(gòu)造函數(shù) :

const LEN = 3;
const arr = new Array(LEN);
assert.equal(arr.length, LEN);
// arr only has holes in it
assert.deepEqual(Object.keys(arr), []);

這種方法很方便,但是有兩個缺點:

  • 即便你稍后再用值把數(shù)組完全填滿,這種空洞也會使這個 Array 略微變慢。

  • 空洞的默認(rèn)值一般不會是元素的初始“值”。常見的默認(rèn)值是零。

Array 構(gòu)造函數(shù)后面加上 .fill() 方法

.fill()方法會更改當(dāng)前的 Array 并使用指定的值去填充它。這有助于在用 new Array() 創(chuàng)建數(shù)組后對其進(jìn)行初始化:

const LEN = 3;
const arr = new Array(LEN).fill(0);
assert.deepEqual(arr, [0, 0, 0]);

警告:如果你用對象作為參數(shù)去 .fill() 一個數(shù)組,所有元素都會引用同一個實例(也就是這個對象沒有被克隆多份):

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]);

這一次,我們創(chuàng)建并填充了一個數(shù)組,同時里面沒有出現(xiàn)漏洞。所以操作這個數(shù)組時應(yīng)該比用構(gòu)造函數(shù)創(chuàng)建的更快。不過 創(chuàng)建 數(shù)組的速度比較慢,因為引擎可能需要隨著數(shù)組的增長多次重新分配連續(xù)的內(nèi)存。

使用 undefined 填充數(shù)組

Array.from() 將 iterables 和類似數(shù)組的值轉(zhuǎn)換為 Arrays ,它將空洞視為 undefined 元素。這樣可以用它將每個空洞都轉(zhuǎn)換為 undefined

> Array.from({length: 3})
[ undefined, undefined, undefined ]

參數(shù) {length:3} 是一個長度為 3 的類似 Array 的對象,其中只包含空洞。也可以使用 new Array(3),但這樣一般會創(chuàng)建更大的對象。
下面這種方式僅適用于可迭代的值,并且與 Array.from()具有類似的效果:

> [...new Array(3)]
[ undefined, undefined, undefined ]

不過 Array.from()通過 new Array() 創(chuàng)建它的結(jié)果,所以你得到的仍然是一個稀疏數(shù)組。

使用  Array.from()  進(jìn)行映射

如果提供映射函數(shù)作為其第二個參數(shù),則可以使用 Array.from() 進(jìn)行映射。

用值填充數(shù)組
  • 使用小整數(shù)創(chuàng)建數(shù)組:

    > Array.from({length: 3}, () => 0)
    [ 0, 0, 0 ]
  • 使用唯一(非共享的)對象創(chuàng)建數(shù)組:

    > Array.from({length: 3}, () => ({}))
    [ {}, {}, {} ]
按照數(shù)值范圍進(jìn)行創(chuàng)建
  • 用升序整數(shù)數(shù)列創(chuàng)建數(shù)組:

    > Array.from({length: 3}, (x, i) => i)
    [ 0, 1, 2 ]
  • 用任意范圍的整數(shù)進(jìn)行創(chuàng)建:

    > const START=2, END=5;
    > Array.from({length: END-START}, (x, i) => i+START)
    [ 2, 3, 4 ]

另一種創(chuàng)建升序整數(shù)數(shù)組的方法是用 .keys(),它也將空洞看作是 undefined 元素:

> [...new Array(3).keys()]
[ 0, 1, 2 ]

.keys()返回一個可迭代的序列。我們將其展開并轉(zhuǎn)換為數(shù)組。

備忘速查:創(chuàng)建數(shù)組

用空洞或 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}, () => ({}))
    [{}, {}, {}] (唯一對象)

用整數(shù)范圍填充:

  • 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]

推薦的模式

我更喜歡下面的方法。我的側(cè)重點是可讀性,而不是性能。

  • 你是否需要創(chuàng)建一個空的數(shù)組,以后將會完全填充?

    new Array(LEN)
  • 你需要創(chuàng)建一個用原始值初始化的數(shù)組嗎?

    new Array(LEN).fill(0)
  • 你需要創(chuàng)建一個用對象初始化的數(shù)組嗎?

    Array.from({length: LEN}, () => ({}))
  • 你需要創(chuàng)建一系列整數(shù)嗎?

    Array.from({length: END-START}, (x, i) => i+START)

如果你正在處理整數(shù)或浮點數(shù)的數(shù)組,請考慮Typed Arrays —— 它就是為這個目的而設(shè)計的。它們不能存在空洞,并且總是用零進(jìn)行初始化。

提示:一般來說數(shù)組的性能無關(guān)緊要
  • 對于大多數(shù)情況,我不會過分擔(dān)心性能。即使是帶空洞的數(shù)組也很快。使代碼易于理解更有意義。

  • 另外引擎優(yōu)化的方式和位置也會發(fā)生變化。今天最快的方案可能明天就不是了。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享JavaScript中怎么創(chuàng)建和填充任意長度的數(shù)組內(nèi)容對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,遇到問題就找億速云,詳細(xì)的解決方法等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI