2

Why in such case,

var a={b:1};
Object.assign(a,{b:a.b+2},{b:a.b+4});

console.log(a);

The result of assign is object

{b: 5}

Rather than

{b: 7}

For the record using this I was trying to explain why value is 1 in below code

// assuming this.state = { value: 0 };
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});
3
  • 1
    it takes the last value for assignment, not the intermediate results. Commented May 21, 2018 at 14:13
  • 1
    Why do you expect {b: 7}? Commented May 21, 2018 at 14:14
  • 1
    The expected value is {b: 5}. The first parameter is the target, the second parameter is assigned (first source) but is overwritten by the third (last source). Commented May 21, 2018 at 14:23

3 Answers 3

4

Because arguments are evaluated before being passed to the function. You're basically doing

var a = {b: 1},
    tmp1 = {b: a.b+2}, // {b: 1+2}
    tmp2 = {b: a.b+4}; // {b: 1+4}
Object.assign(a, tmp1, tmp2);

You would need to do

var a = {b: 1};
Object.assign(a, {b: a.b+2}); // simpler: a.b += 2
Object.assign(a, {b: a.b+4}); // simpler: a.b += 4

to get 7.

Sign up to request clarification or add additional context in comments.

3 Comments

I thought in my case it merged third object ({b:a.b+4}) with second ({b: a.b+2}) and result with a, would not that also be an explanation?
var a = {b: 1}, tmp1 = a.b+2, tmp2 = a.b+4; a.b = tmp1; a.b = tmp2 assign is kinda doing this, if that makes more sense.
@john no, Object.assign puts the object properties from the second argument into the first object and then the object properties from the third argument into the first object. There is no "merge" step (and in the absence of getters/setters, it doesn't make a difference anyway, the rightmost value always overwrites the ones on the left).
0

It's expected a result. Because of Object.assign not sum values, but overwrite. It set values from right to left. The right value is {b: a.b+4} => {b: 5}. This value overlapse other ones.

Comments

0

Object.assign and React's setState work differently. For Object.assign, you can think of it as a right-to-left merge of the objects:

Object.assign(a,{b:a.b+2},{b:a.b+4});
Object.assign(a,{b:3},{b:5});
Object.assign(a,{b:5});

However, setState is a different story. It is an asynchronous operation. In your case, you're simply executing the exact same statement three times:

this.setState({ value: 0 + 1});
this.setState({ value: 0 + 1});
this.setState({ value: 0 + 1});

Multiple setState calls can update state in one event loop and result in a single re-render. Part of the architectural efficiency behind the way setState works may be responsible for this behaviour. This reference may also be helpful:

Why is setState giving me the wrong value?

If you want to use the previous value of a setState operation, you can do somthing like this:

setState((prevState) => ({ value: prevState.value + 1 }));

or

setState({ value: this.state.value + 1 }, () => {
    // In here, the state has been updated
});

However, it's hard to give a precise practical solution as your example is contrived and there would probably be no practical need to do sequential setState operations like that.

See the React documentation for more details on setState.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.