想實(shí)現(xiàn)的目標(biāo)
在js/ts(typescript)項(xiàng)目,經(jīng)常會(huì)遇到使用二維數(shù)組的場(chǎng)景,但js/ts中沒有直接的二維數(shù)組可以使用,間接實(shí)現(xiàn)方法是嵌套一維數(shù)組。
現(xiàn)在項(xiàng)目需初始化NxN的二維數(shù)組,且每個(gè)元素為0,然后程序會(huì)根據(jù)邏輯要求,更新其中的某個(gè)元素值。這有點(diǎn)像是NxN的稀疏矩陣。
初版實(shí)現(xiàn)
有了上述需求,很容易寫出初始化的語句:
let N = 3;
let arr1 = new Array(N).fill(new Array(N).fill(0));
...
arr1[1][2] = 1;
...
代碼很簡(jiǎn)潔,先new Array(N)出N行,再在N行中填充N列,N列同樣使用new Array方式進(jìn)行創(chuàng)建并初始化為0,在創(chuàng)建完后通過輸出arr1值,可以看出,確實(shí)是生成NxN的0矩陣:
image.png

image.png
原因
經(jīng)過再次仔細(xì)上述簡(jiǎn)短的代碼,左看右看還是沒有想到原因在哪里,最后通過瀏覽器的F12工具驗(yàn)證:
image.png
把問題范圍縮小到
new Array(N).fill(new Array(N).fill(0));
這條語句上:原來是JS引用導(dǎo)致的問題?。?!
這條語句,應(yīng)該先是創(chuàng)建了N行數(shù)組,接著調(diào)用fill函數(shù)時(shí),先計(jì)算N列的創(chuàng)建并初始化為N列全0數(shù)組,然后再把N列數(shù)組傳入到原fill函數(shù)中,此時(shí)傳入的N列是同一個(gè)對(duì)象,因此N行數(shù)組的每一行的子數(shù)組都指向了同一個(gè)N列,也就當(dāng)更新某一個(gè)元素時(shí),所有列都變化了,因?yàn)檎麄€(gè)數(shù)組實(shí)際就1行N列。此語句應(yīng)等效于(僅為推測(cè),未查看底層js實(shí)際執(zhí)行過程哈):
let n_cols = new Array(N).fill(0);
let arr1 = new Array(N).fill(n_cols);
整改
let N = 3;
let arr1 = new Array(N).fill(0).map((val) => new Array(N).fill(0));
...
arr1[1][2] = 1;
...
這次就成功啦:
image.png
注意:
需先對(duì)N行使用fill(0)填充后,map才有效果哦!!!