Object Spread VS. Object.Assign

Object spread vs. Object.assign

For reference object rest/spread is finalised in ECMAScript 2018 as a stage 4. The proposal can be found here.

For the most part object assign and spread work the same way, the key difference is that spread defines properties, whilst Object.assign() sets them. This means Object.assign() triggers setters.

It's worth remembering that other than this, object rest/spread 1:1 maps to Object.assign() and acts differently to array (iterable) spread. For example, when spreading an array null values are spread. However using object spread null values are silently spread to nothing.

Array (Iterable) Spread Example

const x = [1, 2, null , 3];
const y = [...x, 4, 5];
const z = null;

console.log(y); // [1, 2, null, 3, 4, 5];
console.log([...z]); // TypeError

Object Spread Example

const x = null;
const y = {a: 1, b: 2};
const z = {...x, ...y};

console.log(z); //{a: 1, b: 2}

This is consistent with how Object.assign() would work, both silently exclude the null value with no error.

const x = null;
const y = {a: 1, b: 2};
const z = Object.assign({}, x, y);

console.log(z); //{a: 1, b: 2}

Object.assign vs object spread operator

TLDR: for small objects, i think they perform similarly

I did some small test using jest.

these all my codes
example are from JSON Data set example

// example 4
const optionsA = {
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}

// example 8
const optionsB = {
"items":
{
"item":
[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}

]
}
}

module.exports = {optionsA, optionsB}

this is Assign.test.js

const { optionsA, optionsB } = require("./Options");

test('jest assign test', () => {
let options = Object.assign({}, optionsA,optionsB);
expect(options).toEqual({
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
],
"items":
{
"item":
[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}

]
}
})
})

this is Spread.test.js

const { optionsA, optionsB } = require("./Options");

test('jest spread test', () => {
let options = {...optionsA,...optionsB};
expect(options).toEqual({
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
],
"items":
{
"item":
[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}

]
}
})
})

And when i do these test, they have similar time doing the work:

Spread test
Assign test

Difference between Object.assign and object spread

The difference is that when using a spread you are always creating a new object:

const a = { name: 'Joe Bloggs' }const b = { ...a, age: 27 };
console.log(a === b) //=> false

Difference between Object.assign and object spread (using [...] syntax)?

In your particular case they are not the same.

The reason is that you have an array, not an object.

Doing ... on an array will spread out all the elements in the array (but not the properties)

Doing Object.assign expects an object so it will treat an array as an object and copy all enumerable own properties into it, not just the elements:

const a = [1, 2, 3];a.test = 'example';
const one = [...a] // [1, 2, 3];const two = Object.assign([], a); // { '0': 1, '1': 2, '2': 3, 'test': 'example' }
console.log('\none');for (let prop in one) { console.log(prop);}
console.log('\ntwo');for (let prop in two) { console.log(prop);}

Why does object spread fail but Object.assign succeeds when updating a DOM element's style attribute?

Why does this happen?

style is a read-only property, and cannot be assigned to a new value.

element.style = { ...element.style, backgroundColor: 'green' };

Creates a shallow copy of element.style, adds/updates the property backgroundColor and assigns the copy back to element.style. For this reason it fails, because you cannot assign element.style a new value.

Object.assign(element.style, { backgroundColor: 'green' });

Assigns each property/value pair in the second argument to element.style. It does not create a copy of element.style, but mutates the element.style object.

Is there a way to replicate Object.assign's desired behaviour with object spread?

No, object spread is used only in object literals, which will always result in a new object being created. You cannot update an existing object using object spread.

Object.assign vs assignment (=)

Assignment only creates another reference to the exact same object in memory. If you assign, then change by referencing one of the variable names, the other one will have changed too, since they're the same thing.

Object.assign will assign all enumerable own properties of the second (and further) parameters to the first parameter, and will return the first parameter. So

const obj3 = Object.assign(obj2, obj1);

is a bit like

for (const prop in obj1) {
obj2[prop] = obj1[prop]
}
obj3 = obj2;

(with plain objects - skipping the own aspect)

They're quite different.

What purpose does spread syntax inside an object literal ({...object}) serve?

It's not the same object. It makes a shallow copy of the object's own, enumerable properties (like Object.assign({}, object) (MDN). You use it when you want...a copy, with the object's own, enumerable properties. :-D

For example, with any of several MVC or similar libraries, you might use it when updating state, since state shouldn't be modified directly:

this.setState(oldState => ({...oldState, prop: "new value"}));

What is the time complexity of object spread operator in Javascript?

It's O(n). Object spread iterates through all enumerable own properties and assigns them to a new object, and property assignment is an O(1) process. If there are N keys to iterate through, there are around N such operations to perform.

That said, this here will not be a bottleneck in 99.9% of actual code, so it's not worth worrying about.

Use Object.assign or Spread Operator in React/Redux? Which is a better practise

Redux docs recommends you to use the spread operator approach instead of the Object.assign

As per the docs:

An alternative approach is to use the object spread syntax proposed
for the next versions of JavaScript which lets you use the spread
(...) operator to copy enumerable properties from one object to
another in a more succinct way. The object spread operator is
conceptually similar to the ES6 array spread operator

The advantage of using the object spread syntax becomes more apparent when you're composing complex objects

Using the Spread operator syntax

export const selectDiameter = (scaleData,size) => {
return {
type: SELECT_DIAMETER,
payload: {...scaleData,
diameter: {
...scaleData.diameter,
selectedTube: size,
isClicked: true,
audio: {
...scaleData.diameter.audio,
isPlayed: true
}
}

}
}
}

It still uses ES6. See the Redux docs for more info on configuring your code for the same

However when you are dealing with the nested data. I prefer to use immutability-helpers

For your code it will be like

import update from 'immutability-helpers';

export const selectDiameter = (scaleData,size) => {
return {
type: SELECT_DIAMETER,
payload: update(scaleData, {
diameter: {
selectedTube: { $set: size},
isClicked: { $set: true},
audio: {
isPlayed: {$set: true}
}
}
})
}
}

add new elements to object just using spread

Try this

const stateObject = {
missouri: ["springfield", "rolla"],
nevada: ["carlin", "vegas"],
}

const addState = (...states) => {
states.forEach(state => stateObject[state] = []);
}

const addCity = (state, ...cities) => {
stateObject[state] = [...stateObject[state], ...cities];
}

// test
addState('California', 'Texas')
addCity('California', 'Los Angeles')
addCity('Texas', 'Austin', 'Houston')
console.log(stateObject)


Related Topics



Leave a reply



Submit