Angular/JS向数组指定索引push值时所有索引被同步填充问题
问题根因
所有子数组同步被填充是JavaScript/TypeScript的引用类型浅引用特性导致的:初始化二维数组的子数组时,把同一个数组对象的引用重复push到外层数组,会导致外层数组所有索引位都指向内存中同一个数组实例,不管通过哪个索引操作这个数组,所有指向它的引用都会同步体现修改。
看原生JS复现代码里的初始化逻辑:
for (let index = 0; index < this.numberofColumns; index++) { this.matrixColumns.push(columnsMatrix); // 每次push的都是提前声明的同一个columnsMatrix空数组 }
这段代码执行后,matrixColumns里的9个元素存的都是同一个空数组的内存地址,没有生成9个独立的子数组。后续给matrixColumns[columnIndex]执行push操作,本质都是修改那唯一的一个数组,最后打印时9个位置自然全是内容相同的完整数组。
你贴的Angular版本代码里初始化写的是this.matrixColumns.push([]),这段逻辑本身不会触发引用问题,如果Angular项目里出现同样报错,大概率是实际代码和原生JS复现版逻辑一致,push了提前声明的同一个数组变量,而非每次新建空数组。
修复方案
- 修正子数组初始化逻辑:循环初始化子数组时,每次都生成全新的空数组,不要复用同一个数组引用
for (let index = 0; index < this.numberofColumns; index++) { this.matrixColumns.push([]); // 每次push新创建的独立空数组,每个子数组都是单独的实例 } - 清理无效冗余代码:原forEach循环里手动写的
matrixIndex = matrixIndex + 1属于无效逻辑,forEach回调的索引参数会自动递增,手动修改不会影响外层遍历的索引值,可以直接删除。
修复后完整代码
class AppComponent { matrix = [ 1, 2, 3, 4, 5, 6, 7, 8, 9.1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, ]; matrixColumns = []; numberofColumns = 9; constructor() { this.createColumnMatrix(); } createColumnMatrix() { // 初始化9个独立的空子数组 for (let index = 0; index < this.numberofColumns; index++) { this.matrixColumns.push([]); } let columnIndex = 0; this.matrix.forEach((number) => { this.matrixColumns[columnIndex].push(number); columnIndex++; if (columnIndex > this.numberofColumns - 1) { columnIndex = 0; } }); } } let component = new AppComponent(); for (let row of component.matrixColumns) { console.log(JSON.stringify(row)); }
运行结果
执行后输出和预期逻辑一致:
[1,10,19,28,37] [2,11,20,29,38] [3,12,21,30,39] [4,13,22,31,40] [5,14,23,32,41] [6,15,24,33,42] [7,16,25,34,43] [8,17,26,35,44] [9.1,18,27,36,45]
注:原一维数组第9个元素值为
9.1,你写的预期结果里对应位置是9,属于预期值的笔误,代码逻辑是严格按照原数组元素顺序填充的。
内容的提问来源于stack exchange,提问作者ccocker
相关产品推荐
相关产品推荐

