AppDividend
Latest Code Tutorials

Object.assign: How to Copy Object Values in JavaScript

2

In the object-oriented programming world, we already know the importance of classes and objects. Unlike all the other programming languages, JavaScript does not have any traditional classes seen in different programming languages. Still, JavaScript has objects and constructors which work mostly in the same way to perform the same kind of operations.

There are two types of constructors in JavaScript,

  1. Built-in constructors(array and Object)
  2. Custom constructors(define properties and methods for specific objects).

The Object constructor creates the object wrapper for the given value.

If the value is null or undefined, it will create and return the empty Object; Otherwise, it will return the object of a type corresponding to a given value.

If the value is the Object already, it will return the value.

When called in the non-constructor context, Object behaves identically to new Object ().

Properties of the Object constructor

  1. Object.length

    It has a value of 1.

  2. Object.prototype

    It allows the addition of properties to all objects of the type Object. Methods of the Object constructor.

Object.assign in JavaScript

The Object.assign() is a built-in JavaScript function that is used to copy the values of all own enumerable properties from one or more source objects to the target object. The Object.assign() method takes target and sources as parameters and returns the target object.

The Object.assign() method is used for cloning an object or merging the objects shallowly. It merges objects with the same properties. The properties in the sources will overwrite properties in a target object if they have the same key.

From the many Object constructor methods,  Object.assign() is one method that is used to copy the values and properties from one or more source objects to a target object.

Syntax

The syntax for a Javascript Object assign() method is the following.

Object.assign(target, ...sources)

Parameters

A target parameter is a target object.

The sources parameter are the objects that need to be cloned.

Return Value

The Object.assign() method returns a the target object.

Example

Let us take a simple example by cloning the Object.

// app.js

let obj = { name: 'Krunal', surname: 'Lathiya' };
let cloneObj = Object.assign({}, obj);
console.log(cloneObj);

In the above example, we have defined one Object, and then we have created a clone of that object with a new object. The output will be the following.

Javascript Object Assign Example | Object.assign() Tutorial

So, it has copied all the properties from a source object.

Let us merge three objects with Object.assign() method.

// app.js

let o1 = { a: 21 };
let o2 = { b: 22 };
let o3 = { c: 24 };

Object.assign(o1, o2, o3);
console.log(o1);

Javascript Object Assign Example

Merging objects with the same properties

If the properties get repeated inside the source objects, then in the clone object, the repeated properties will be skipped, and we only get the unique properties on the target object.

// app.js

let o1 = { a: 21, b: 22, c: 24 };
let o2 = { b: 22, c: 24 };
let o3 = { c: 24 };

let finalObj = Object.assign({}, o1, o2, o3);
console.log(finalObj);

Object.assign() Tutorial

Immutablity of Object.assign() method

Let’s see the following example.

// app.js

let obj = {
  eleven: 'Millie Bobby Brown',
  mike: 'Finn Wolfhard',
};
let objCopy = Object.assign({}, obj);
console.log(objCopy);

objCopy.mike = 'Noah Schnapp';
console.log(objCopy);
console.log(obj);

See the output.

➜  es git:(master) ✗ node app
{ eleven: 'Millie Bobby Brown', mike: 'Finn Wolfhard' }
{ eleven: 'Millie Bobby Brown', mike: 'Noah Schnapp' }
{ eleven: 'Millie Bobby Brown', mike: 'Finn Wolfhard' }
➜  es git:(master) ✗

In the code above, we changed the value of a property ‘mike’ in objCopy Object to ‘Noah Schnapp‘, and when we log a modified objCopy object in the console, the changes only apply to objCopy.

The last line of the code checks that the obj object is still intact and hasn’t changed.

This means that we have successfully created a copy of a source object without any references to it.

Pitfall of Object.assign() In Javascript

Let’s discuss a little bit about shallow copying. See the following code example.

// app.js

let obj = {
  a: 11,
  b: {
    c: 21,
  },
}
let newObj = Object.assign({}, obj);
console.log('First use of Object.assign() method')
console.log(newObj);
console.log('-------------------------------')

obj.a = 10;
console.log('Modify the obj\'s "a" property');
console.log(obj);
console.log(newObj);
console.log('-------------------------------')

newObj.a = 19;
console.log('Modify the newObj\'s "a" property');
console.log(obj);
console.log(newObj);
console.log('-------------------------------')

newObj.b.c = 29;
console.log('Modify the newObj\'s "b"\'s "c" property');
console.log(obj);
console.log(newObj);

See the output.

➜  es git:(master) ✗ node app
First use of Object.assign() method
{ a: 11, b: { c: 21 } }
-------------------------------
Modify the obj's "a" property
{ a: 10, b: { c: 21 } }
{ a: 11, b: { c: 21 } }
-------------------------------
Modify the newObj's "a" property
{ a: 10, b: { c: 21 } }
{ a: 19, b: { c: 21 } }
-------------------------------
Modify the newObj's "b"'s "c" property
{ a: 10, b: { c: 29 } }
{ a: 19, b: { c: 29 } }
➜  es git:(master) ✗

So, here Properties on the prototype chain and non-enumerable properties cannot be copied.

Now, let’s understand. Shallow copy and deep copy in Javascript.

What is a shallow copy in Javascript?

When we say we are making a shallow copy of an Array or Object, what that means is that we are creating new references to the primitive values inside the Object, copying them. What that means is changes to an original array will not affect the copied array, which would happen if only the reference to an array had been copied (that would occur with the assignment operator =).

A shallow copy cites that only one level is copied, and that will work fine for the array or Object containing only primitive values.

For objects and arrays containing other objects or arrays, copying these objects requires a deep copy. Otherwise, the nested references’ modification will modify the data nested in an original Object or array.

What is a deep copy in Javascript?

For Javascript objects and arrays containing other objects or arrays, copying these objects needs a deep copy. Otherwise, modifications made to the nested references will change the data nested in the original Object or array.

This is compared to the shallow copy, which works fine for the object or array containing only primitive data type values, but will fail for any object or array with nested references to other objects or arrays.

If we understand the difference between == and === can help us visually see the difference between shallow and deep copy, as the strict equality operator (===) shows that the nested references are the same.

A deep copy of an Object in Javascript

Object.assign() is the standard way of copying an object in JavaScript. And also spread operator does the same. Both methodologies can be equivalently used to copy the enumerable properties of an object to another object, with the spread operator being the shorter of the two. They are also handy to merge objects since both methods automatically overwrite the properties in the target object that have the same keys as those in the source object.

A deep copy will duplicate every Object it encounters. The copy and the original Object will not share anything to be a copy of the original.

The spread operator and the Object.assign() method can only make shallow copies of objects. This means that the deeply nested values inside the copied Object are put there to reference the source object. If we modify the copied Object’s deeply nested value, we will, therefore, end up modifying the value in the source object.

JSON.parse(JSON.stringify(object));

I have already written one article on how we can parse JSON in Javascript. Suppose you don’t know what json.parse() does, then please check out that article. Now, this fixes the issue of the above problem.

This fixes the issue we had earlier. Now, newObj.b has a copy and not a reference! This is a way to deep copy objects.

See the following code example.

// app.js

let obj = {
  a: 11,
  b: {
    c: 21,
  },
}

let newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 29;
console.log(obj);
console.log(newObj);

See the output.

➜  es git:(master) ✗ node app
{ a: 11, b: { c: 29 } }
{ a: 11, b: { c: 21 } }
➜  es git:(master) ✗

Benchmarking of Object.assign() and Spread Operator

The Object spread operator {…obj} is similar to Object.assign(). So the question is which one should you use? And it turns out the answer is a bit more nuanced than you might expect.

The foundation idea of the object spread operator and Object.assing() the same, to create a new plain object using the own properties of the existing object.

For performance checking, we will use the benchmark library.

You can install the benchmark library using the following command.

npm install --save benchmark

 Now, write the following code inside the app.js file.

const Benchmark = require('benchmark');

const suite = new Benchmark.Suite;

const obj = { prop: 'krunal', attr: 'ankit' };

suite.
  add('Spread Operator', function () {
    ({ data: 'rushabh', ...obj });
  }).
  add('Object.assign()', function () {
    Object.assign({ data: 3 }, obj);
  }).
  on('cycle', function (event) {
    console.log(String(event.target));
  }).
  on('complete', function () {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
  }).
  run({ 'async': true });

Output

Spread Operator x 11,986,798 ops/sec ±4.60% (74 runs sampled)
Object.assign() x 11,734,098 ops/sec ±5.52% (74 runs sampled)
Fastest is Spread Operator,Object.assign()
➜ node app
Spread Operator x 14,660,760 ops/sec ±1.03% (84 runs sampled)
Object.assign() x 14,409,887 ops/sec ±0.85% (85 runs sampled)
Fastest is Spread Operator
➜ node app
Spread Operator x 14,382,964 ops/sec ±1.30% (78 runs sampled)
Object.assign() x 13,730,209 ops/sec ±1.00% (86 runs sampled)
Fastest is Spread Operator
➜ node app
Spread Operator x 14,540,831 ops/sec ±1.19% (78 runs sampled)
Object.assign() x 14,520,784 ops/sec ±0.69% (86 runs sampled)
Fastest is Object.assign()

You can see that the Object.assign() and Spead operator are interchangeable, and both are faster. But if you provide the empty object, then the Spread operator is even faster than Object.assign().

Benchmarking aims at evaluating something by comparison with standard procedure. However, the question here is that why we need benchmarking in the case of software programming. Benchmarking the code means how fast the code is executing and where the bottleneck is.

In this example, we have seen the comparison between Object.assign() and Spread Operator, and we have experimented with the benchmark module.

Object.assign() changes the object in place to trigger the ES6 setters. If you prefer immutable techniques, then the object spread operator is a clear winner. With Object.assign(), you have to always pass an empty object {} as the first argument.

Another related difference is that the spread operator defines new properties, whereas Object.assign() sets them. Object.assign() calls setters defined on Object.prototype, whereas the spread operator does not.

So that is it for the comparison.

Conclusion

Object.assign() and spread operator enables us to make only shallow copies of objects in JavaScript. Deeply nested values are put there just as a reference to the source object.

Finally, Object.assign() In Javascript example is over.

Recommended Posts

Javascript Object.freeze()

Javascript Object.toString()

Javascript Object.values()

Javascript Object.keys()

Javascript Object.create()

2 Comments
  1. ngoc danh says

    tks friend

  2. good says

    Object.assign doesn’t show immutability. Here it only shows the difference of assignment by copy and by reference.

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.