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

JavaScript中避免修改原对象,传递对象的最佳方式及替代方案

关于JavaScript中避免修改原对象的方案解析

你已经明确JavaScript中对象是按引用传递,在函数内修改会影响原对象,并且用扩展运算符{...obj}创建副本的方式是可行的,但它属于浅拷贝,是否是“最佳方案”得看你的具体场景,下面给你几种常见的替代方案和适用场景:

一、浅拷贝方案(适合单层结构对象)

如果你的对象只有一层属性(没有嵌套的对象/数组),这些方法足够用:

  • 扩展运算符:就是你用的const newObj = {...obj},写法简洁直观,是日常开发中最常用的方式之一。
  • Object.assign():和扩展运算符效果完全一致,const newObj = Object.assign({}, obj),同样只复制对象的第一层属性。

注意:浅拷贝的局限性在于,若对象里嵌套了其他对象或数组,拷贝后嵌套部分依然是引用关系,修改嵌套内容还是会影响原对象。

二、深拷贝方案(适合多层嵌套结构)

如果对象有多层嵌套,需要彻底切断和原对象的引用关系,就得用深拷贝:

  • JSON序列化/反序列化:const newObj = JSON.parse(JSON.stringify(obj)),写法最简单,但有明显局限——无法处理函数、Symbol、循环引用、undefined这些类型,会直接丢失这些内容,适合结构简单且无特殊类型的对象。
  • 手写递归深拷贝:可以自定义处理各种数据类型,适合有特殊需求的场景,示例代码:
    function deepClone(obj) {
      // 非对象类型直接返回
      if (obj === null || typeof obj !== 'object') return obj;
      // 处理Date类型
      if (obj instanceof Date) return new Date(obj);
      // 处理数组类型
      if (obj instanceof Array) return obj.map(item => deepClone(item));
      // 处理普通对象
      const newObj = {};
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          newObj[key] = deepClone(obj[key]);
        }
      }
      return newObj;
    }
    
  • 第三方库(如Lodash的_.cloneDeep()):如果项目中已经引入了Lodash这类工具库,直接用_.cloneDeep(obj)最省心,它能处理各种边界情况,成熟稳定。

三、不可变数据工具(适合频繁修改不可变数据的场景)

如果你的业务需要频繁处理不可变数据(比如React状态管理),可以用Immer库,它允许你以“直接修改”的写法操作副本,底层自动生成新的不可变对象,代码更简洁:

import { produce } from 'immer';

function test(obj) {
  const newObj = produce(obj, draft => {
    draft.a = 7; // 这里看似修改原对象,实际是操作Immer生成的草稿对象,最终返回新对象
  });
}

总结

  • 单层对象:扩展运算符或Object.assign()是轻量高效的最佳选择;
  • 多层嵌套对象:根据是否有特殊类型,选择JSON方法(简单场景)、手写深拷贝(自定义需求)或第三方库(稳定可靠);
  • 频繁处理不可变数据:Immer能大幅提升开发体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:13:36