You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环赋值二维数组仅存最后值:如何存入变量当前值而非引用?

问题本质:引用类型的传递特性

在JavaScript中,数组属于引用类型,而非值类型。你每次调用rangeArray.push(rowArray)时,并没有把rowArray的当前值复制进去,而是把它在内存中的引用地址存到了rangeArray里。整个循环过程中,你始终在修改同一个rowArray的内容,所有已经存入rangeArray的引用都会指向这个被反复修改的数组,最终所有元素自然都是最后一次修改后的结果。

触发场景

这种问题会在以下场景出现:

  • 循环中重复使用同一个引用类型变量(数组、对象等),并多次将其添加到另一个容器中
  • 后续代码会修改这个引用类型变量的内部状态
最优解决方法

核心思路是:每次向rangeArray中添加时,存入的是当前数组的副本,而非原数组的引用。以下是几种可靠的实现方式:

方法1:每次循环内创建新数组

把rowArray的声明放到外层循环内部,让每次循环都生成一个全新的数组,从根源避免引用复用:

var rangeArray = [];
for (k = 0; k < 5; k++){
  // 每次循环新建一个数组,不存在引用共享问题
  var rowArray = [];
  for (var i = 0; i < 6; i++){ 
    rowArray[i] = ((i+1) *(k+1));
  }
  rangeArray.push(rowArray);
}
Logger.log(rangeArray);

方法2:使用数组拷贝方法生成副本

如果需要保留原数组的初始结构,每次push前可以创建当前rowArray的浅拷贝,常用的拷贝方式有三种:

  • slice():无参数调用时返回原数组的浅拷贝
  • [...rowArray]:扩展运算符快速生成拷贝
  • Array.from(rowArray):通过Array.from创建拷贝

修改后的代码示例:

var rowArray = [".", ".", ".", ".", ".", "."];
var rangeArray = [];
for (k = 0; k < 5; k++){
  for (var i = 0; i < 6; i++){ 
    rowArray[i] = ((i+1) *(k+1));
  }
  // 推入当前数组的副本,而非原引用
  rangeArray.push(rowArray.slice());
  // 也可以用扩展运算符:rangeArray.push([...rowArray]);
}
Logger.log(rangeArray);

方法3:直接在循环中生成目标数组(更简洁)

可以省略单独的rowArray变量,直接在每次循环里生成目标行数组:

var rangeArray = [];
for (k = 0; k < 5; k++){
  // 用Array.from直接生成当前行的数组并推入
  rangeArray.push(Array.from({length:6}, (_, i) => (i+1)*(k+1)));
}
Logger.log(rangeArray);
为什么临时方法不可靠?

你用toString().split(",")的方式本质是一种取巧的hack,存在明显缺陷:

  • 如果数组元素本身包含逗号(比如字符串"a,b"),拆分后会被错误地分割成两个元素
  • 数值会被转换为字符串类型,后续可能需要额外的类型转换操作
  • 性能远不如直接的数组拷贝方法

内容的提问来源于stack exchange,提问作者Андрей Косенко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:23:13