32

Simplifying the Object.assign Method in JavaScript

 5 years ago
source link: https://www.tuicool.com/articles/hit/ZfANN3J
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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.

mAZnQrE.png!web

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.

Fja6Nv3.png!web

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  cat object. 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:

67RrUzQ.png!web

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:

e2eaiy2.png!web

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:

eErui2R.png!web

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:

6VjEZbi.png!web

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:

aiyMfuy.png!web

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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK