首頁  >  文章  >  web前端  >  JavaScript中建立和填入任意長度的陣列方法介紹(附程式碼)

JavaScript中建立和填入任意長度的陣列方法介紹(附程式碼)

不言
不言轉載
2019-02-25 10:18:5314123瀏覽

這篇文章帶給大家的內容是關於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中建立和填入任意長度的陣列方法介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除