new Array和Array.from误区

86 阅读1分钟

最近在刷算法题,发现一个有趣的现象,涉及到了底层的一些逻辑。 如果你要实现一个二维数组如5*3,会怎么做

var dp = new Array(5).fill(new Array(3).fill(0))

这是不是很多不接触js算法的人的做法,但是这有个大问题,当你更改dp[0][0]的值得时候你会发现,dp[1][0]的值也会变更(同一列都会变更),相信很多人马上就看出来了,这是因为每行fil的二维数组,是同一个对象引用,也就是说,会先生成一个对象引用,然后给fill去使用,就算用其他的函数生成也无效。

var genI = ()=>new Array(3).fill(0)
var dp = new Array(5).fill(genI())
//
var dp = new Array(5).fill([...new Array(3)])

都会出现这个问题。原理就是会先生成这个对象,再被fill引用,而不是一个循环复制的过程(很多人理解中,fill是forEach循环,然后进行回调,其实不是)。 那么怎么实现呢,当然可以用for循环去吧new Array(5)去每个push一个新的3长度数组,但是这很戳,所以这就用到了Array.from的第二个参数。

const dp = Array.from(Array(5), () => Array(3).fill(0))

第一个参数是数字或类数组(可迭代对象,注意,map也可迭代包括weakmap,但是weakmap和weakSet迭代出来的东西是空数组),第二个参数就是每个迭代对象item的回调函数,返回值就是每一项的最终值。