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

ReactJS:提取子数组修改后父数组同步变更问题排查

父数组随子数组修改同步变更的原因及解决方法

问题描述

从父数组中提取子数组后,为子数组元素添加新键值对时,父数组也随之被修改。以下是相关代码及输出:

代码示例

const array = [{"integrationTypeId":1,"type":"aptus","fields":[{"name":"base_url"},{"name":"hash_key"}]}]

function runArray(){
let connectorObject= {}
let newArray
if (array.length > 0) {
                connectorObject =
                    array.find(
                        (c) => c.integrationTypeId === 1,
                    );
                newArray = connectorObject.fields
                newArray !== undefined &&
                    newArray.map((object) => {
                        return Object.assign(object, {
                            inputType: "textField",
                            value: object.name,
                        })
                    })
            }
            console.log(JSON.stringify(newArray))
            console.log(JSON.stringify(array))
}

runArray();

输出结果

Console 1. : newArray

[{"name":"base_url","inputType":"textField","value":"base_url"},{"name":"hash_key","inputType":"textField","value":"hash_key"}]

Console 2. : Parent Array

[{"integrationTypeId":1,"type":"aptus","fields":[{"name":"base_url","inputType":"textField","value":"base_url"},{"name":"hash_key","inputType":"textField","value":"hash_key"}]}]

尝试使用newArray.map(obj => ({ ...obj, inputType: "textField"}))也未解决该问题。

原因分析

JavaScript里,对象和数组都是引用类型。当你执行newArray = connectorObject.fields时,并没有复制出一个新的子数组,只是让newArray指向了父数组中fields数组的内存地址。后续用Object.assign直接修改数组内的对象时,本质是在修改原内存地址里的对象,父数组自然会同步变化。

至于你尝试的map方法没生效,是因为你只调用了map但没把返回的新数组赋值给newArray。map本身会返回包含新对象的新数组(通过扩展运算符...创建),但如果不把这个结果存起来,newArray仍然指向原来的数组,原对象还是会被修改。

解决方法

要避免修改父数组,需要创建子数组及其中对象的浅拷贝(如果对象没有嵌套结构,浅拷贝足够)。

方法1:用map直接生成新数组和新对象

把map的返回值赋值给newArray,同时通过扩展运算符创建新对象,不改动原对象:

const array = [{"integrationTypeId":1,"type":"aptus","fields":[{"name":"base_url"},{"name":"hash_key"}]}]

function runArray(){
let connectorObject= {}
let newArray
if (array.length > 0) {
    connectorObject = array.find((c) => c.integrationTypeId === 1);
    // 生成包含新对象的新数组
    newArray = connectorObject.fields.map((object) => ({
        ...object,
        inputType: "textField",
        value: object.name
    }));
}
console.log(JSON.stringify(newArray))
console.log(JSON.stringify(array))
}

runArray();

方法2:先拷贝数组再替换对象

如果需要保留原数组的操作逻辑,可以先拷贝数组,再逐个替换为新对象:

const array = [{"integrationTypeId":1,"type":"aptus","fields":[{"name":"base_url"},{"name":"hash_key"}]}]

function runArray(){
let connectorObject= {}
let newArray
if (array.length > 0) {
    connectorObject = array.find((c) => c.integrationTypeId === 1);
    // 先拷贝原fields数组
    newArray = [...connectorObject.fields];
    // 遍历新数组,替换为带新属性的新对象
    newArray = newArray.map((object) => ({
        ...object,
        inputType: "textField",
        value: object.name
    }));
}
console.log(JSON.stringify(newArray))
console.log(JSON.stringify(array))
}

runArray();

注意事项

如果你的数组对象存在多层嵌套(比如fields里的对象还有子对象),需要用深拷贝,比如JSON.parse(JSON.stringify(connectorObject.fields)),或者用Lodash的_.cloneDeep工具函数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:55:28