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

如何使用Array find方法获取值而非引用避免原数组突变

核心原因

JavaScript中数组存储对象时,实际存储的是对象的内存引用,Array.find()方法返回的就是原对象的引用,因此修改返回值会直接变更原数组中的对应元素。要避免原数组被修改,只需对查找到的对象做拷贝后再操作即可,根据对象结构不同可以选择以下方案:


方案1:浅拷贝(适用单层无嵌套引用的对象)

如果你的对象所有属性都是字符串、数字、布尔值等基本类型,没有嵌套的对象、数组等引用类型,用浅拷贝就足够,性能开销最小:

async getModifiedRecord(id, attrs){
    const records = await this.getAll();
    const rawRecord = records.find(record => record.id === id);
    // 用展开运算符做浅拷贝
    const copiedRecord = {...rawRecord};
    // 或者用Object.assign生成新对象
    // const copiedRecord = Object.assign({}, rawRecord);
    
    // 此时修改copiedRecord完全不会影响原records数组
    Object.assign(copiedRecord, attrs);
    return copiedRecord;
}

方案2:深拷贝(适用存在嵌套引用的对象)

如果对象包含嵌套对象、数组、Map、Set等复杂类型,浅拷贝只能复制第一层结构,嵌套部分仍为原引用,修改后还是会影响原对象,此时需要做深拷贝:

  • 方案2.1 原生structuredClone方法(推荐)
    ES2022新增的浏览器/Node.js原生支持的深拷贝方法,支持处理Date、RegExp、循环引用等绝大多数常见场景,仅不支持函数、Symbol类型:
    const copiedRecord = structuredClone(rawRecord);
    
  • 方案2.2 JSON序列化反序列化
    兼容性好,适合简单场景,但存在较多限制:无法处理函数、Symbol、undefined、循环引用,Date类型会被转为字符串,正则会丢失属性:
    const copiedRecord = JSON.parse(JSON.stringify(rawRecord));
    
  • 方案2.3 工具库实现
    如果项目引入了Lodash等工具库,可以直接使用封装好的深拷贝方法,边界情况处理更完善:
    const copiedRecord = _.cloneDeep(rawRecord);
    

补充说明

如果你原本的需求是要修改后将整个records数组持久化存储,那你最初的写法是符合预期的,不需要额外做拷贝,因为你需要将修改同步到数组后再执行写入操作。只有当你需要对查询结果做临时修改、不需要污染原数组时,才需要做拷贝处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:39:03