Appearance
Object Spread vs Object Assign
We can extend an object with either Object Spread operator or Object.assign():
js
// With Object Spread
const sourceObj = { foo: 'bar' };
const extendedObj = {
...sourceObj,
newProp: 'a',
};
js
// With Object.assign()
const sourceObj = { foo: 'bar' };
const extendedObj = Object.assign(sourceObj, { newProp: 'a' });
There are subtle differences between the two approaches. See below.
Object Prototypes
The spread operator will not copy the the source object’s prototype to the target object. This is outlined in more detail here.
Notable observations with Class instances and getters & setters:
js
class Person {
constructor(str) {
this.str = str;
}
get str() {
return this._str;
}
set str(str) {
this._str = str;
}
greet() {
return 'Hello';
}
}
var p = new Person('abc');
var spreadObj = {
...p,
newProp: 'a',
};
var assignedObj = Object.assign(p, { newProp: 'a' });
console.log(spreadObj);
/**
* {
* _str: 'abc',
* newProp: 'a'
* }
*
* Note that this is a plain object
*/
console.log(spreadObj.str);
/**
* undefined
*/
console.log(spreadObj.greet());
/**
* TypeError: spreadObj.greet is not a function
*/
console.log(assignedObj);
/**
* Person {
* _str: 'abc',
* newProp: 'a'
* }
*
* Note that this is instance of Person
*/
console.log(assignedObj.str);
/**
* 'abc'
*/
console.log(assignedObj.greet());
/**
* 'Hello'
*/
Source Object Mutation
With the spread operator, a new literal object extendedObj
is defined and the sourceObj
remains untouched; Object.assign()
mutates the sourceObject
, and returns it.
js
const sourceObj = { foo: 'bar' };
const extendedObj = {
...sourceObj,
newProp: 'a',
};
console.log(sourceObj);
/**
* {
* foo: 'bar'
* }
*/
js
const sourceObj = { foo: 'bar' };
const extendedObj = Object.assign(sourceObj, { newProp: 'a' });
console.log(sourceObj);
/**
* {
* foo: 'bar',
* newProp: 'a'
* }
*/
Triggering set
Object.assign()
triggers set
while spread operator does not.
js
const objectAssign = Object.assign(
{
set foo(val) {
console.log(val);
},
},
{ foo: 1 },
);
// Logs "1"; objectAssign.foo is still the original setter
const spread = {
set foo(val) {
console.log(val);
},
...{ foo: 1 },
};
// Nothing is logged; spread.foo is 1