首頁  >  文章  >  web前端  >  如何用js快速初始化數組

如何用js快速初始化數組

一个新手
一个新手原創
2017-09-09 10:43:042843瀏覽

標籤(空格分隔): call apply


筆記版

#編寫程式碼中通常會有快速初始化陣列的需求,例如我們需要一個類似matlab裡的zeros函數,假如這裡我們需要產生一個0-23的陣列用來表示一天24小時。
最基本的做法如下:

function(){
    let hours = [];    
    for(let k = 0; k < 24; k++ )
    hours.push(k);    
    return hours;
}

下面我們來思考如何用更優雅的方式實現。
考慮使用new Array(24)+ map的方法來實作。
程式碼如下:

Array(24).map((_, h) => h);

注意,這裡map的第二個參數是索引,平常用的少,這裡把索引當作數值。
結果與預期並不符合,為啥呢?
簡單搜尋了一下,發現時因為js裡的稀疏數組的邏輯導致的。
我們先來看看下面的程式碼:

let a = [];
a[1000] = 2;
console.log(a.length);// 1000a.forEach(x => console.log("hello"));// only one "hello"

js的處理邏輯是,對於沒有主動賦值的位置進行「空置」處理,對於這些「空置」未知,迭代器是不會理會的,這麼做最主要的目的就是避免不合理的賦值操作所導致的bug。
假設沒有這種邏輯,我們寫下了new Array(Date.now()),這將導致系統新建一個非常大的數組,而實際上啥也沒存。
我們可以吧new Array(len)幹的事情簡單理解為下面的過程:

function(len){
    let r = [];
    r.length = len;    
    return r;

這就是為什麼對new Array(len)調用mapforEach的時候跟預期不一致了。
如何解決這個問題呢,除了使用new Array(len)的形式,我們還可以使用new Array(1,2,3)這種寫法來初始化數組,但是這麼寫就沒辦法實現我們寫初始化數組的目的了。
這時候我們想到了apply,這個函數的第二個參數剛好就是一個數組,於是我們寫下了下面的程式碼。

// 借用apply
Array.apply(null, Array(24)).map((_, h) => h);
// [0, 1, ..., 24]

得到了我們希望的結果。這就說明,Array(24)apply中當作參數的時候是被當做24個值對待的,因為這一點就保證了最後得到的陣列長度是24。
既然如此,我們當然同樣可以使用apply的姊妹函數call

// 借用call
Array.call(null, ...Array(24)).map((_, h) => h);
// [0, 1... 23]

這也更確認了一件事,Array(len)解構會得到len個參數而非一個參數,當然call的使用必須在支援解構操作符的環境中。

在熟悉了callapply的原理後,我們可以進一步寫出下面的程式碼:

// Array本身
Array(...Array(24)).map((_, h) => h);
// [0, 1, ..., 24]

這種形式已經足夠優雅了。
另外,在ES6中,Array提供了新方法fill,借用該方法填充那些「空置」位,進而保證後續的操作能順利進行。
具體程式碼如下:

// 推荐
Array(24).fill(null).map((_, h) => h);

現在也比較推薦最後一種寫法,這種方法也最為直覺。
不過要注意fill方法的使用,應該盡量避免盲目地填充,因為這樣會上面提到了js設計「空置」邏輯為了避免的bug。
有興趣的可以嘗試下面的程式碼:

// no-fillconsole.time("no-fill");let t = Array(5e7);console.timeEnd("no-fill");// fillconsole.time("fill");let q = Array(5e7).fill(null);console.timeEnd("fill");// => no-fill: 0.240ms// => fill: 3247.921ms

在瀏覽器中嘗試瀏覽器基本上會不回應,沒有設定更大的數值為了避免得不到結果。假設一個int佔用4個位元組的內存,這個fill會佔用200M的內存,而且需要循環5千萬次,這必然會佔用大量的CPU和內存,在單線程的js中是絕對不允許的。

#

以上是如何用js快速初始化數組的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn