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

循环数组仅保留最后值?JavaScript数组引用问题排查

为什么数组中对象的属性值被后续循环覆盖?

我写了一段JavaScript代码,想要生成包含数组的数组对象,但实际输出和期望不符:

代码示例

var cars = [{ a: 1 }, { a: 2 }];
var arr = [
  { a: 0, name: "as" },
  { a: 0, name: "aa" },
];
var fin = [];

for (let i in cars) {
  const asd = cars[i].a;
  for (let j in arr) {
    if (arr[j].name == "as") {
      arr[j].a = asd;
    }
  }
  fin.push(arr);
}

console.log(fin);

实际输出

[[{ a: 2, name: "as" },{ a: 0, name: "aa" }],[{ a: 2, name: "as" },{ a: 0, name: "aa" }]]

期望输出

[[{ a: 1, name: "as" },{ a: 0, name: "aa" }],[{ a: 2, name: "as" },{ a: 0, name: "aa" }]]

为什么fin[0][0].a没有保留1,反而被改成了2?


原因分析

这是JavaScript引用类型的特性导致的:

  • arr是数组,属于引用类型,在内存中存储的是一个地址,而非具体值。
  • 每次循环调用fin.push(arr)时,并没有复制arr的内容存入,而是把arr的内存地址存进了fin数组。
  • 第一次循环修改arr中name="as"的对象a值为1,将arr的地址push到fin;第二次循环又修改同一个arr里的对象a值为2,再push同一个地址。
  • 最终fin里的两个元素都指向内存中同一个arr数组,打印时自然都是最后一次修改后的结果。

解决方法

每次循环时,创建arr的浅拷贝(因数组元素是对象,需同时复制对象),修改拷贝后的数组,再将其push到fin。

修改后的代码如下:

var cars = [{ a: 1 }, { a: 2 }];
var arr = [
  { a: 0, name: "as" },
  { a: 0, name: "aa" },
];
var fin = [];

for (let i in cars) {
  const asd = cars[i].a;
  // 复制原数组及内部对象
  const newArr = arr.map(item => ({ ...item }));
  for (let j in newArr) {
    if (newArr[j].name == "as") {
      newArr[j].a = asd;
    }
  }
  fin.push(newArr);
}

console.log(fin);

这里用arr.map(item => ({ ...item }))生成原数组的浅拷贝:map创建新数组,{...item}用对象展开语法复制每个对象的属性,确保每次循环操作的是独立的数组和对象,不会互相干扰。


内容的提问来源于stack exchange,提问作者Anas Al-Saadi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:42:21