The Object.assign Method in JavaScript Explained | JavaScript Tutorial

In JavaScript, an object's assign method copies the source object’s own enumerable properties to a target object and returns that target object.
There are two important keywords in the above sentence:
  1. Enumerable
  2. Own
Before we go ahead and understand the purpose of Object.assign, it is essential that we really understand these two words, enumerable properties and own properties. Let's examine them one by one. 
A JavaScript object could have either enumerable or non-enumerable properties. However, by default, when you create a property on an object, it is enumerable.  Enumerable means you can enumerate through those properties. Let's understand it through code.
const babycat = {
    age: '1',
    color: 'white'
}
for (var prop in babycat) {
    console.log(prop);
}
There are two properties in babycat object. By default, both are enumerable, hence. as the output of the for...in loop, you will get both the age and name printed.
Now let us change the default enumerable behavior of the age property using the Object.defineProperty method.
const babycat = {
    age: '1',
    color: 'white'
}
Object.defineProperty(babycat, 'age', { enumerable: false });
for (var prop in babycat) {
    console.log(prop);
}
We have changed the enumerable of the age property to false, so, as an output, only the color will be printed. Hence, age is no longer an enumerable property of the babycat object.
Another keyword in the above sentence is own properties. To understand it, you need to understand the object prototype chain. All JavaScript objects are part of a prototype chain and thus can access properties of its prototype.  So, own properties are those properties which are particular to the object and not from the prototype chain. Let's look at own properties through some code examples:



const cat = {
    name: 'foo'
}
const babycat = {
    age: '1',
    color: 'white'
}
//babycat.__proto__ = cat; // I love this more 
Object.setPrototypeOf(babycat, cat);
for (var prop in babycat) {
    console.log(prop);
}
In the above code snippet, there are two objects, cat and babycat. In addition, the [[Prototype]] property of the  babycat object is set to the catobject. When you print the properties of the babycat object using a for...in loop, output age, color, and name will be printed, as shown in the below image:
What is happening here? Well, JavaScript prints all the properties from the prototype chain. However, only age and color are own properties of the babycat object.
Now that we've gone over own properties and enumerable properties the in context of a JavaScript object, let us revisit the first statement of this post: In JavaScript, an object’s assign method copies the source object’s own enumerable properties to a target object and returns that target object. 
Consider the code below:  
const cat = {
    name: 'foo'
}
const babycat = Object.assign({}, cat);
for (var prop in babycat) {
    console.log(prop + ':' + babycat[prop]);
}
Using the Object.assign() method, we are copying the cat object's own enumerable properties to the babycat object. Here, the cat object is the source and the babycat object is the target. You will get the output printed as below:
The Object.assign() method uses [[Get]] on the source object and [[set]] on the target object and invokes setters and getters to perform the task. Essentially, it assigns property values from the source to the target object. It does not create a new property in the target object.
Let us examine some variations while copying properties from the source object to a target object.

Same Properties in Both Target and Source Objects

If the target object has the same properties as the source object, then Object.assign() method will override target object properties. Consider the code below:
const cat = {
    name: 'foo',
    age: 9
}
const babycat = Object.assign({ age: 1 }, cat);
for (var prop in babycat) {
    console.log(prop + ':' + babycat[prop]);
}
There is an age property in both the target object and source object. While copying the properties in the target object, the Object.assign() method will override the target object's age property. Thus, you will get the output shown in the below image:

Deep Cloning of Objects

As we saw in pervious examples, cloning can be performed using the Object.assign() method. To refresh, the below code snippet performs the cloning.
const cat = {
    name: 'foo',
    age: 9
}
const babycat = Object.assign({}, cat);
for (var prop in babycat) {
    console.log(prop + ':' + babycat[prop]);
}
The Object.assign() method copies values. Thereforthe e, if source object has a reference type, it will copy the reference value. Let us understand it through code:
const cat = {
    name: 'foo',
    age: 9,
    child: {
        nochild: 2
    }
}
const babycat = Object.assign({}, cat);
console.log(cat.name); // foo
console.log(babycat.name); // foo 
console.log(cat.child.nochild); // 2
console.log(babycat.child.nochild); // 2
babycat.name = 'koo';
babycat.child.nochild = 9;
console.log(cat.name); // foo
console.log(babycat.name); // koo 
console.log(cat.child.nochild); // 9
console.log(babycat.child.nochild); // 9
In the above example, the Object.assign method will copy:
  • The value of name and age.
  • The value of the child reference, as it is of reference type.
Since, for the name property, only the value is copied, when you change its value in the babycat object, it does not affect the cat object’s name property. However, when you change the value of the child property on the babycat object, it changes the value of the cat object also, because of its reference type nature. As expected, when you run the above sample, you will get an output as shown below:

Merging More Than One Source Object

Using the Object.assign() method, you can also merge more than one object to a target object. Consider the code listed below:
const obj1 = {
    a: 1
}
const obj2 = {
    b: 2
}
const obj3 = {
    c: 3
}
const obj4 = Object.assign({}, obj1, obj2, obj3, { d: 4 });
for (let p in obj4) {
    console.log(obj4[p]);
}
We are merging obj1obj2obj3, and the unnamed object to target, obj4. You will get the output printed below:

Null and Undefined

JavaScript's Object.assign() method ignores null and undefined while copying objects. Consider the code listed below:


const obj1 = {
    a: 1
}
const obj2 = Object.assign({}, obj1, null, undefined, { d: 4 });
for (let p in obj2) {
    console.log(obj2[p]);
}
As output, you will get 1 and 4 printed because the assign method ignores undefined and null.
You should use JavaScript's Object.assign() method to copy the source object’s own enumerable properties to the target object. It does clone objects, by copying the value from the source object.

Post a Comment

1 Comments