Reputation: 12015
As I know spread operator return a new object after operation:
let a = {a:1};
let b = {a: 2}
let a = {...a,...b}
So, last a
is not referenced to a
, it is a new object in memory.
Is it possible to use spread operator without changing initial object, I mean a reference in memory?
Upvotes: 2
Views: 579
Reputation: 1397
Spread operator only works on primitive types.
Here an example with primitive datatypes:
let x = {
number: 1
}
let y = { ...x
}
x.number++
console.log(x)
console.log(y)
Non Primitive:
let x1 = {
numbers: {
number: 1
}
}
let y1 = { ...x1
}
x1.numbers.number++
console.log(x1)
console.log(y1)
As you can see, the 2nd version still uses references, to bypass this use a deep clone function like this:
let x1 = {
numbers: {
number: 1
}
}
let y1 = copy(x1)
x1.numbers.number++
console.log(x1)
console.log(y1)
function copy(aObject) { // Deep Clone Object from https://stackoverflow.com/a/34624648/16642626
if (!aObject) {
return aObject;
}
let v;
let bObject = Array.isArray(aObject) ? [] : {};
for (const k in aObject) {
v = aObject[k];
bObject[k] = (typeof v === "object") ? copy(v) : v;
}
return bObject;
}
So if u truly want to keept the reference, you could nest the a and b in ur example so that the spread operator is not able to see the primitive types on the first layer
Upvotes: 1
Reputation: 255015
It's guaranteed by the 12.2.6.7 Runtime Semantics: Evaluation
and 12.2.6.8 Runtime Semantics: PropertyDefinitionEvaluation
that the object returned from an object literal with "spread syntax" is always a new object.
Relevant parts of the spec:
- Let
obj
beObjectCreate(%ObjectPrototype%)
.
and
PropertyDefinition:...AssignmentExpression
1. LetexprValue
be the result of evaluatingAssignmentExpression
.
2. LetfromValue
be ?GetValue(exprValue)
.
3. LetexcludedNames
be a new empty List.
4. Return? CopyDataProperties(object, fromValue, excludedNames)
.
There is currently no other way to mutate the object other than just assigning its properties directly.
As @Heretic Monkey noted in the comments: the question is tagged as typescript
while I'm answering about javascript
. The thing is that TS compiler must retain the native js runtime semantics, so in this very case it's okay to refer to the ES2018 standard.
Upvotes: 3