JavaScript Copying and comparing objects

Copying objects

Unlike primitive data types, object data is copied by reference. What does it mean? Consider the following example:

const tom = {name: "Tom"};
const bob = tom;
// check the name property of both constants
console.log(tom.name); // Tom
console.log(bob.name); // Tom
        
// change the name property of the bob constant
bob.name="Bob";
// re-check the name property of both constants
console.log("After change")
console.log(tom.name); // Bob
console.log(bob.name); // Bob

First, an ordinary object tom with one property is a defined name. Then we assign the value of this object to a constant bob

const bob = tom;

In this case, the constant bob gets a reference or, relatively speaking, the address of a constant tom, so after this assignment, both constants essentially point to the same object in memory. Accordingly, changes made through one constant:

bob.name="Bob";

Another constant is also affected – tom:

console.log(tom.name); // Bob\

Moreover, let’s add a new property to the object through one of the constants:

const tom = {name: "Tom"};
const bob = tom;
// add new property to bob constant - age
bob.age = 37;
// and we see that a new property has also been added for tom
console.log(tom.age); // 37

After adding a property to a constant bob, you can see that the constant tom also has this property, because again, both constants represent the same object.

What if we want to copy from a property of an object, but at the same time both constants or variables would point to completely different objects, changes in one of which would not affect the other in any way? In this case, we can use the built-in Object.assign() method .

Object.assign method

The Object.assign() method takes two parameters:

Object.assign(target, ...sources)

The first parameter target represents the object into which to copy the properties. The second parameter is …sources a set of objects from which to copy properties (that is, we can copy properties from several objects at once)

Returns the method of the target object, into which the properties from the objects are copied sources.

For example:

const tom = { name: "Tom", age: 37};
const bob = Object.assign({}, tom);
bob.name = "Bob";
bob.age = 41;
        
console.log(`Объект tom. Name: ${tom.name}   Age: ${tom.age}`);
console.log(`Объект bob. Name: ${bob.name}   Age: ${bob.age}`);

In this case, the call Object.assign({}, tom)means that we are copying the data from the object tom to an empty object {}. The result of this copying is a bob. Moreover, this is a completely different object than tom. And any changes to the constant bob here will not affect the constant in any way tom.

Console output of the program:

tom object. Name: Tom Age: 37
bob. Name: Bob Age: 41
Copy from multiple objects

Similarly, you can copy data from multiple objects:

 
const tom = { name: "Tom"};
const sam = { age: 37};
const person = { height: 170};
Object.assign(person, tom, sam);    // копируем из tom и sam в person
console.log(person);    // {height: 170, name: "Tom", age: 37}

This copies all the properties from the tom and sam objects to the person object. As a result, after copying, the person object will have three properties.

Copy properties of the same name

If the objects being copied from containing the same properties, then the properties from the last objects replace the properties of the previous ones:

const tom = { name: "Tom", age: 37};
const sam = { age: 45};
const person = { height: 170};
Object.assign(person, tom, sam);
console.log(person);    // {height: 170, name: "Tom", age: 45}

Here, both objects, tom, and sam, contain a property age, but in the person object, the age property is 45, the value from the sam object, because the sam object is copied last.

Copying object properties

While this Object.assign() works great for simple objects, what happens if the property of the copied object also represents the object:

const tom = { name: "Tom", company: {title: "Microsoft"}};
const bob = Object.assign({}, tom);
bob.name = "Bob";
bob.company.title = "Google";
console.log(tom.name);      // Tom
console.log(tom.company.title);     // Google

Here, a company objects property represents an object with a single property. And when copying the bob object, it will not receive a copy of the value tom.company, but a reference to this object. Therefore, the changes bob.company will affect and tom.company.

Copying an object using the spread operator

The spread operator … allows you to spread an object into different pairs property-value that can be passed to another object.

 
const tom = { name: "Tom", age: 37, company: "Google"};
const bob = {...tom}
bob.name = "Bob";
         
console.log(tom);   // {name: "Tom", age: 37, company: "Google"}
console.log(bob);   // {name: "Bob", age: 37, company: "Google"}

In this case, bob, copies of the properties of the tom object are passed to the object.

If some properties of the new object should have other values (as in the example above, the name property), then they can be specified at the end:

const tom = { name: "Tom", age: 37, company: "Google"};
const bob = {...tom, name: "Bob"};
       
console.log(bob);   // {name: "Bob", age: 37, company: "Google"}

As you can see from the previous example, both constants after copying represent references to different objects, and changing one of them will not affect the other object in any way.

However, if the objects contain nested objects, then these nested objects, when copied, will again essentially represent references to the same object:

const tom = { name: "Tom", age: 37, Company: {title: "Microsoft"}};
const bob = {...tom}
bob.name="Bob";
bob.company.title = "Google";

console.log(`${tom.name} - ${tom.company.title}`); // Tom - Google
console.log(`${bob.name} - ${bob.company.title}`); // Bob - Google

Object Comparison

Let’s compare two objects using standard comparison and equivalence operations:

const tom = {name: "Tom"};
const bob = {name: "Bob"};
console log(tom == bob); // false
console log(tom === bob); // false

Both operators in this case will return the value false, that is, the objects are not equal. Moreover, even if the values ​​of the properties of the objects are the same, then in both cases we will still get false

const tom = {name: "Tom"};
const bob = {name: "Tom"};
console log(tom == bob); // false
console log(tom === bob); // false

However, what happens if both constants (variables) store a reference to the same object:

const tom = {name: "Tom"};
const bob = tom;
console log(tom == bob); // true
console log(tom === bob); // true

In this case, in both cases, we will get true, since the values ​​of both constants are equal since in fact, this is the same value.