Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object.assign(...as) changes input parameter

Tags:

javascript

Object.assign(...as) appears to change the input parameter. Example:

const as = [{a:1}, {b:2}, {c:3}];
const aObj = Object.assign(...as);

I deconstruct an array of object literals as parameter of the assign function. I omitted console.log statements. Here's the stdout from node 13.7:

as before assign: [ { a: 1 }, { b: 2 }, { c: 3 } ]

aObj: { a: 1, b: 2, c: 3 }

as after assign: [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]

The reader may notice that as first element has been changed in an entire. Changing a new array bs elements to an immutable object (using freeze)

const bs = [{a:1}, {b:2}, {c:3}];
[0, 1, 2].map(k => Object.freeze(bs[k]));
const bObj = Object.assign(...bs);

leads to an error:

TypeError: Cannot add property b, object is not extensible at Function.assign (<anonymous>)

Which indicates the argument is indeed being changed.

What really confounds me is that even binding my array, cs, by currying it to a function (I think you call this a closure in JS)

const cs = [{a:1}, {b:2}, {c:3}];
const f = (xs) => Object.assign(...xs);
const g = () => f(cs);                            

const cObj = g();

returns:

cs before assign: [ { a: 1 }, { b: 2 }, { c: 3 } ] cObj: { a: 1, b: 2, c: 3 } cs after assign: [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]

What went wrong here? And how may one safely use Object.assign without wrecking its first argument?

like image 833
gschenk Avatar asked Nov 25 '25 04:11

gschenk


1 Answers

Object.assign is not a pure function, it writes over its first argument target.

Here is its entry on MDN:

Object.assign(target, ...sources)

Parameters

target

The target object — what to apply the sources’ properties to, which is returned after it is modified.

sources

The source object(s) — objects containing the properties you want to apply.

Return value

The target object.

The key phrase is "[the target] is returned after it is modified". To avoid this, pass an empty object literal {} as first argument:

const aObj = Object.assign({}, ...as);
like image 104
gschenk Avatar answered Nov 27 '25 17:11

gschenk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!