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

JavaScript中调用Array.map后temp变量为何会被同步修改?

问题原因

核心原因是JavaScript的对象引用共享特性,和map方法的返回规则直接相关:

  • Array.map()确实会返回一个全新的数组,不会修改原数组本身的结构
  • 但map不会自动深拷贝数组里的元素:你在回调里直接返回原student对象时,新数组里存的是指向原对象的内存引用,不是对象的独立副本
  • 你在回调里写student.status = 'xxx'的时候,修改的是内存里的原对象本身,所有指向这个对象的引用访问到的都是修改后的值
代码执行流程拆解
  1. 第一次生成temp.actions时:
    遍历到yearsCompleted === 4的Sarah对象,直接把这个对象的status改为'wow',再把对象引用存入新数组。此时temp.actions[2]和原数组objectsArray[2]指向内存中同一个对象。第一次打印temp时,对象状态是修改后的wow,符合预期。
  2. 第二次生成temp2.actions时:
    再次遍历到同一个Sarah对象,直接把它的status改为'foo',同样把对象引用存入temp2的新数组。此时内存里的Sarah对象本身已经被修改,不管是temp.actions里存的引用、原数组里的引用、还是temp2.actions里的引用,访问到的都是被改成foo的同一个对象,所以后续打印temp时会看到status被改成了foo。
修复方法

不要在map回调里直接修改原对象,而是返回一个新建的对象副本,切断引用关联:

const objectsArray = [
    {'id': 1, 'name': 'Erik', 'yearsCompleted': 2, 'status': 'student'}, 
    {'id': 2, 'name': 'Carol', 'yearsCompleted': 1, 'status': 'student'}, 
    {'id': 3, 'name': 'Sarah', 'yearsCompleted': 4, 'status': 'student'}
];

const temp = {
    actions: objectsArray.map(student => {
        // 用展开运算符创建对象副本,仅修改副本属性,不影响原对象
        if (student.yearsCompleted === 4) {
            return {...student, status: 'wow'}
        }
        return {...student}
    })
}

const temp2 = {
    actions: objectsArray.map(student => {
        if (student.yearsCompleted === 4) {
            return {...student, status: 'foo'}
        }
        return {...student}
    })
}

修改后temp、temp2、原数组三者的对象完全独立,后续操作不会互相影响。


内容的提问来源于stack exchange,提问作者Michael Gee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 10:15:57