Redux:如果不执行深度克隆,为什么要使用 Object.assign? [英] Redux: why using Object.assign if it is not perform deep clone?

查看:19
本文介绍了Redux:如果不执行深度克隆,为什么要使用 Object.assign?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Redux 的一个核心概念是,状态是不可变.但是,我看到了很多例子,包括在 Redux docs 使用 javascript Object.assign.然后,我在 MDN:

<块引用>

对于深度克隆,我们需要使用其他替代方案,因为Object.assign() 复制属性值.如果源值是一个引用一个对象,它只复制那个引用值.

那么,如果重点是不变性,为什么要使用 Object.assign 呢?我在这里遗漏了什么吗?

解决方案

让我们看看你链接的例子:

<块引用>

function todoApp(state = initialState, action) {开关(动作.类型){案例 SET_VISIBILITY_FILTER:返回 Object.assign({}, state, {可见性过滤器:action.filter})默认:返回状态}}

是的,这是 state 的浅拷贝,使用旧的所有内容创建一个新对象,但具有更新的 visibilityFilter.但是,如果您一致处理对象不可变,那么如果新状态和旧状态共享对其他不可变对象的引用就可以了.后来,大概,如果您要更改其他内容,您将遵循相同的模式.此时,我们上面制作的浅拷贝将继续使用旧的,而您的新对象将使用新的.

如果您一直应用不变性,那么您只需要在您正在修改的级别及其所有父级别上的浅拷贝.在上面的例子中,修改是在顶层,所以它只是一个副本.

但如果它更深呢?假设你有这个对象:

let obj = {一个: {a1: "a1 初始值",a2: "a2 初始值"},乙:{b1: "b1 初始值",b2: "b2 初始值"}};

如果你想更新a,就像上面的状态示例一样;你只需要一个 obj 的浅拷贝即可:

obj = Object.assign({}, obj, {a: {a1: "new a1", a2: "new a2"}});

或使用传播属性(目前处于第 3 阶段,通常在 JSX 中启用)转译器设置,可能会在 ES2018 中实现):

obj = {...obj, a: {a1: "new a1", a2: "new a2"}};

但是如果您只是想要更新a1怎么办?为此,您需要 a obj 的副本(因为如果您不复制 obj,您正在修改它所指的树,违反了主体):

obj = Object.assign({}, obj, {a: Object.assign({}, obj.a, {a1: "updated a1"})});

或具有传播属性:

obj = {...obj, a: {...obj.a, a1: "updated a1"}};

One core concept in Redux is, states are immutable. However, I saw many examples, including in Redux docs using javascript Object.assign. Then, I saw this warning in MDN:

For deep cloning, we need to use other alternatives because Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value.

So, why using Object.assign if the whole point is immutability? Am I missing something here?

解决方案

Let's look at the example you linked:

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}

Yes, that's a shallow copy of state, creating a new object with everything from the old but with an updated visibilityFilter. But if you're consistent about treating objects immutably, then it's fine if the new state and the old state share references to other immutable objects. Later, presumably, if you were to change something else, you'd follow the same pattern. At which point, the shallow copy we made above would continue to use the old one, and your new object would use the new one.

If you apply immutability all the way down, a shallow copy at the level you're modifying and all its parent levels is all you need. In the example above, the modification is at the top level, so it's just the one copy.

But what if it were deeper? Let's say you had this object:

let obj = {
    a: {
        a1: "a1 initial value",
        a2: "a2 initial value"
    },
    b: {
        b1: "b1 initial value",
        b2: "b2 initial value"
    }
};

If you wanted to update a, that's just like the state example above; you'd do so with just one shallow copy of obj:

obj = Object.assign({}, obj, {a: {a1: "new a1", a2: "new a2"}});

or with spread properties (currently at Stage 3, usually enabled in JSX transpiler setups, will probably make ES2018):

obj = {...obj, a: {a1: "new a1", a2: "new a2"}};

But what if you just want to update a1? To do that, you need a copy of a and of obj (because if you don't copy obj, you're modifying the tree it refers to, violating the principal):

obj = Object.assign({}, obj, {a: Object.assign({}, obj.a, {a1: "updated a1"})});

or with spread properties:

obj = {...obj, a: {...obj.a, a1: "updated a1"}};

这篇关于Redux:如果不执行深度克隆,为什么要使用 Object.assign?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆