gpt4 book ai didi

javascript - 使用 Object.assign 对对象所做的更改会改变源对象

转载 作者:行者123 更新时间:2023-12-01 15:12:18 25 4
gpt4 key购买 nike

我的 react-redux 应用程序中有以下 reducer 代码:

    case 'TOGGLE_CLIENT_SELECTION':
const id = action.payload.id;
let newState = Object.assign({}, state);
newState.list.forEach((client) => {
if (client.id == id) client.selected = !client.selected;
});
console.log(state.list[0].selected + ' - ' + newState.list[0].selected)
return newState;

如果我做对了 - Object.assign 创建了全新的对象,但 console.log 显示“假 - 假”的“真 - 真”。有什么想法为什么它会这样,我该如何避免这种行为?

最佳答案

Object.assign 创建一个浅克隆
Object.assign将属性复制到另一个对象。其中一些属性是“按值”复制的,而其他属性是“按引用”复制的。字符串、数字和 bool 值是“按值”,而对象(包括日期)是“按引用”,这意味着它们指向同一个对象。

因此,例如,给定:

var otherState = { count: 10 };

var state = { text: "foo", otherState: otherState };

var newState = Object.assign({}, state);

newState.text = "bar";
newState.otherState.count = 9;
newState.text将有一个全新的字符串分配给它,并且状态不会受到影响。但两者都是 statenewState引用 otherState 的同一个实例, 所以当你更新 count到 9,两个 state.otherState.countnewState.otherState.count被影响到的:
state = {
text = "foo"
otherState ──────┐
} │


├────> { count = 9 }

newState = { │
text = "bar" │
otherState ──────┘
}

使用 Object.assign 时,使用三的规则:如果你到达第三个属性,你现在处于“共享”状态:
newState.otherState.count = 0;
// ^ ^ ^
// ╵ ╵ ╵
// 1 2 3

JSON.parse 来救援(?)

一个快速简单的解决方法,如 suggested by Tim ,就是使用 JSON.stringify:
let newState = JSON.parse(JSON.stringify(state));

但这并非万无一失。它适用于一些简单的场景,但有很多场景可能会失败。例如,循环引用会破坏 JSON.stringify:

let x = { id: "x" },
y = { id: "y" };
x.y = y;
y.x = x;

// fails with: "Uncaught TypeError: Converting circular structure to JSON"
let cloneX = JSON.parse(JSON.stringify(x));


自定义克隆代码救援(?)

如果您知道要克隆的结构,那么您可以使用自己的逻辑来处理复制,而不会陷入无限循环:

function cloneX( x ){
const c_x = { id: x.id };
const c_y = { id: x.y.id };
c_x.y = c_y;
c_y.x = c_x;
return c_x;
}

let x = { id: "x" },
y = { id: "y" };
x.y = y;
y.x = x;

let x2 = cloneX(x);
x2.y.id = "y2";

console.log( `x2.y.id was updated: ${x2.y.id}` );
console.log( `x.y.id is unchanged: ${x.y.id}` );


也可以想象,通过一些创造性的使用 WeakMap ,你可以想出一些通过跟踪递归和允许深拷贝来处理未知数据结构的逻辑。

NPM 来救援(?)

可能会更容易 use a library , 尽管。

关于javascript - 使用 Object.assign 对对象所做的更改会改变源对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43074256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com