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

为何常量defaultMap会被修改?如何正确实例化带默认值的Map?

为什么我的常量默认对象会被意外修改?如何解决?

问题场景

我定义了一个带默认值的常量对象:

const defaultMap: MapType = {
      val1: 0,
      val2: 0,
};

接着在React的useEffect中尝试创建多个基于这个默认对象的实例,遍历数组修改它们的属性后,发现原本的defaultMap被意外修改了:

const useMaps = () => {
  useEffect(() => {
    let map1 = defaultMap;
    let map2 = defaultMap;
    let map3 = defaultMap;

    console.log(defaultMap) // 预期输出{val1:0, val2:0},但实际已被修改

    ['val1', 'val2'].forEach((arrayVal) => {
      map1[arrayVal] = 1
      map2[arrayVal] = 2
      map3[arrayVal] = 3
    });

    // 用map1、map2、map3设置状态
  })
}

原因分析

  • JavaScript中对象是引用类型,const关键字仅保证变量本身的引用不可被重新赋值,但它指向的对象内容是可以修改的。
  • 执行let map1 = defaultMap时,并没有创建新的对象,只是让map1、map2、map3都指向了defaultMap所在的内存地址。这三个变量本质上是同一个对象的不同引用,修改它们的属性,其实就是直接修改defaultMap本身。

解决方案

需要为每个map创建独立的对象副本,避免共享内存引用:

1. 浅拷贝(适用于无嵌套的简单对象)

  • 使用扩展运算符:
    let map1 = {...defaultMap};
    let map2 = {...defaultMap};
    let map3 = {...defaultMap};
    
  • 使用Object.assign:
    let map1 = Object.assign({}, defaultMap);
    let map2 = Object.assign({}, defaultMap);
    let map3 = Object.assign({}, defaultMap);
    

2. 深拷贝(适用于含嵌套结构的对象)

如果defaultMap包含嵌套对象或数组,浅拷贝只会复制外层引用,内层结构仍会共享,此时需要深拷贝:

  • 使用JSON.parse(JSON.stringify(defaultMap))(注意:无法处理函数、Symbol等特殊类型):
    let map1 = JSON.parse(JSON.stringify(defaultMap));
    
  • 自定义深拷贝函数或使用第三方工具(如Lodash的_.cloneDeep):
    import _ from 'lodash';
    let map1 = _.cloneDeep(defaultMap);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:20:32