javascript快速初始化數(shù)組

標簽(空格分隔): call apply


筆記版

編寫代碼中通常會有快速初始化數(shù)組的需求毛仪,例如我們需要一個類似matlab里的zeros函數(shù)宦棺,假如這里我們需要生成一個0-23的數(shù)組用于表示一天24小時。
最基本的做法如下:

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

下面我們來思考如何用更優(yōu)雅的方式實現(xiàn)。
考慮使用new Array(24)+ map的方法來實現(xiàn)踪宠。
代碼如下:

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

注意,這里map的第二個參數(shù)是索引妈嘹,平時用的少柳琢,這里把索引作為數(shù)值。
結果與預期并不符合润脸,為啥呢柬脸?
簡單搜索了一下,發(fā)現(xiàn)時因為js里的稀疏數(shù)組的邏輯導致的毙驯。
我們先看一下下面的代碼:

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

js的處理邏輯是倒堕,對于沒有主動賦值的位置進行“空置”處理,對于這些“空置”未知爆价,迭代器是不會理會的垦巴,這么做最主要的目的就是避免不合理的賦值操作導致的bug。
假設沒有這種邏輯铭段,我們寫下了new Array(Date.now())骤宣,這將導致系統(tǒng)新建一個非常大的數(shù)組,而實際上啥也沒存序愚。
我們可以吧new Array(len)干的事情簡單理解為下面的過程:

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

這就是為什么對new Array(len)調用map或者forEach的時候跟預期不一致了涯雅。
如何解決這一問題呢,除了使用new Array(len)的形式展运,我們還可以使用new Array(1,2,3)這種寫法來初始化數(shù)組活逆,但是這么寫就沒法實現(xiàn)我們編寫初始化數(shù)組的目的了。
這個時候我們想到了apply拗胜,這個函數(shù)的第二個參數(shù)正好就是一個數(shù)組蔗候,于是我們寫下了下面的代碼。

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

得到了我們希望的結果埂软。這就說明锈遥,Array(24)apply中作為參數(shù)的時候是被當做24個值對待的纫事,因為這一點就保證了最后得到的數(shù)組長度是24。
既然如此所灸,我們當然同樣可以使用apply的姊妹函數(shù)call丽惶。

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

這也更確認了一件事,Array(len)解構會得到len個參數(shù)而非一個參數(shù)爬立,當然call的使用必須在支持解構操作符的環(huán)境中钾唬。

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

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

這種形式已經(jīng)足夠優(yōu)雅了侠驯。
另外抡秆,在ES6中,Array提供了新方法fill吟策,借用該方法填充那些“空置”位儒士,進而保證后續(xù)的操作能順利進行。
具體代碼如下:

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

現(xiàn)在也比較推薦最后一種寫法檩坚,這種方法也最為直觀着撩。
不過需要注意fill方法的使用,應該盡量避免盲目地填充匾委,因為這樣會上面提到了js設計“空置”邏輯為了避免的bug睹酌。
有興趣的可以嘗試一下下面的代碼:

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

在瀏覽器中嘗試瀏覽器基本會不響應,沒有設置更大的數(shù)值為了避免得不到結果剩檀。假設一個int占用4個字節(jié)的內存憋沿,這個fill會占用200M的內存,且需要循環(huán)5千萬次沪猴,這必然會占用大量的CPU和內存辐啄,在單線程的js中是絕對不允許的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末运嗜,一起剝皮案震驚了整個濱河市壶辜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌担租,老刑警劉巖砸民,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異奋救,居然都是意外死亡岭参,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門尝艘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來演侯,“玉大人,你說我怎么就攤上這事背亥∶爰剩” “怎么了悬赏?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長娄徊。 經(jīng)常有香客問我闽颇,道長,這世上最難降的妖魔是什么寄锐? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任兵多,我火速辦了婚禮,結果婚禮上锐峭,老公的妹妹穿的比我還像新娘中鼠。我一直安慰自己可婶,他們只是感情好沿癞,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矛渴,像睡著了一般椎扬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上具温,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天蚕涤,我揣著相機與錄音,去河邊找鬼铣猩。 笑死揖铜,一個胖子當著我的面吹牛,可吹牛的內容都是我干的达皿。 我是一名探鬼主播天吓,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼峦椰!你這毒婦竟也來了龄寞?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤汤功,失蹤者是張志新(化名)和其女友劉穎物邑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滔金,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡色解,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了餐茵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冒签。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖钟病,靈堂內的尸體忽然破棺而出萧恕,到底是詐尸還是另有隱情刚梭,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布票唆,位于F島的核電站朴读,受9級特大地震影響,放射性物質發(fā)生泄漏走趋。R本人自食惡果不足惜衅金,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望簿煌。 院中可真熱鬧氮唯,春花似錦、人聲如沸姨伟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夺荒。三九已至瞒渠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間技扼,已是汗流浹背伍玖。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剿吻,地道東北人窍箍。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像丽旅,于是被迫代替她去往敵國和親椰棘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容