Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
359 views
in Technique[技术] by (71.8m points)

javascript - Redux: why using Object.assign if it is not perform deep clone?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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"}};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...