top

Objects, object properties and object copy in Javascript

Let’s talk simple things about object like adding properties, copy or deep copy object and Method defined for Object. Objects in JavaScript, just as in many other programming languages, can be compared to objects in real life. The concept of objects in JavaScript can be understood with real life, tangible objects. In JavaScript, an object is a standalone entity, with properties and type. Compare it with a cup, for example. A cup is an object, with properties. A cup has a color, a design, weight, a material it is made of, etc. The same way, JavaScript objects can have properties, which define their characteristics. Objects and Properties A JavaScript object has properties associated with it. A property of an object can be explained as a variable that is attached to the object. Object properties are basically the same as ordinary JavaScript variables, except for the attachment to objects. Properties of JavaScript objects can also be accessed or set using a bracket notation (for more details see property accessors). Objects are sometimes called associative arrays, since each property is associated with a string value that can be used to access it. So, for example, you could access the properties of the myCar object as follows: myCar['make'] = 'Ford'; myCar['model'] = 'Mustang'; myCar['year'] = 1969; An object property name can be any valid JavaScript string, or anything that can be converted to a string, including the empty string. Please note that all keys in the square bracket notation are converted to String type, since objects in JavaScript can only have String type as key type. For example, in the above code, when the key obj is added to the myObj, JavaScript will call the obj.toString()method, and use this result string as the new key. You can also access properties by using a string value that is stored in a variable: var propertyName = 'make'; myCar[propertyName] = 'Ford'; propertyName = 'model'; myCar[propertyName] = 'Mustang'; You can use the bracket notation with for...in to iterate over all the enumerable properties of an object. To illustrate how this works, the following function displays the properties of the object when you pass the object and the object's name as arguments to the function: So, the function call showProps(myCar, "myCar") would return the following: myCar.make = Ford myCar.model = Mustang myCar.year = 1969 Enumerate the properties of an object Starting with ECMAScript 5, there are three native ways to list/traverse object properties: 1. for...in loops: This method traverses all enumerable properties of an object and its prototype chain 2. Object.keys(o): This method returns an array with all the own (not in the prototype chain) enumerable properties' names ("keys") of an object o. 3. Object.getOwnPropertyNames(o) : This method returns an array containing all own properties' names (enumerable or    not) of an object o. Creating new objects JavaScript has a number of predefined objects. In addition, you can create your own objects. You can create an object using an object initializer. Alternatively, you can first create a constructor function and then instantiate an object invoking that function in conjunction with the new operator. Using object initializers In addition to creating objects using a constructor function, you can create objects using an object initializer. Using object initializers is sometimes referred to as creating objects with literal notation. “Object initializer” is consistent with the terminology used by C++. The syntax for an object using an object initializer is: var obj = { property_1:   value_1,   // property_# may be an identifier...           2:            value_2,   // or a number...           // ...,           'property n': value_n }; // or a string Using a constructor function Alternatively, you can create an object with these two steps: 1. Define the object type by writing a constructor function. There is a strong convention, with good reason, to use a capital initial letter. 2. Create an instance of the object with new. 3. To define an object type, create a function for the object type that specifies its name, properties, and methods. For example, suppose you want to create an object type for cars. You want this type of object to be called car, and you want it to have properties for make, model, and year. To do this, you would write the following function: function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } Notice the use of this to assign values to the object's properties based on the values passed to the function. Now you can create an object called mycar as follows: var mycar = new Car('Eagle', 'Talon TSi', 1993); Using the Object.create method Objects can also be created using the Object.create() method. This method can be very useful, because it allows you to choose the prototype object for the object you want to create, without having to define a constructor function. Few Important methods: Object.assign() Copies the values of all enumerable own properties from one or more source objects to a target object. Object.create()              Creates a new object with the specified prototype object and properties. Object.defineProperty()              Adds the named property described by a given descriptor to an object. Object.defineProperties()              Adds the named properties described by the given descriptors to an object. Object.entries()              Returns an array of a given object’s own enumerable property [key, value] pairs. Object.freeze()              Freezes an object: other code can’t delete or change any properties. Let's talk about Object Copy The Naive Way of Copying Objects The naive way of copying objects is looping through the original object and copying each property one after the other. Let’s take a look at this code: Inherent Issues 1. ObjCopy object has a new Object.prototype method different from the mainObj object prototype method, which is not what we want. We want an exact copy of the original object. 2. Property descriptors are not copied. A “writable” descriptor with value set to be false will be true in the objCopy object. 3. The code above only copies enumerable properties of mainObj. 4. If one of the properties in the original object is an object itself, then it will be shared between the copy and the original making their respective properties point to the same object. Shallow Copying Objects An object is said to be shallow copied when the source top-level properties are copied without any reference and there exist a source property whose value is an object and is copied as a reference. If the source value is a reference to an object, it only copies that reference value to the target object. A shallow copy will duplicate the top-level properties, but the nested object is shared between the original(source) and the copy(target). Using Object.assign() method The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. In the code above, we changed the value of the property 'b' in objCopyobject to 80 and when we log the modified objCopy object in the console, the changes only apply to objCopy. The last line of code checks that the objobject is still intact and hasn't change. This implies that we have successfully created a copy of the source object without any references to it. Pitfall of Object.assign() Not so fast! While we successfully created a copy and everything seem to be working fine, remember we discussed shallow copying? Let’s take a look at this example: Why is obj.b.c = 30? we have problem here Note: Properties on the prototype chain and non-enumerable properties cannot be copied. See here: Deep copy of object A deep copy will duplicate every object it encounters. The copy and the original object will not share anything, so it will be a copy of the original. Here’s the fix to the problem we encountered using Object.assign(). Let's explore another option to fix this. Using JSON.parse(JSON.stringify(object)); 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. Here's an example: Another Way is Deep clone function cloneObject(obj) {   var clone = {};   for(var i in obj) {      if(obj[i] != null &&  typeof(obj[i])=="object")           clone[i] = cloneObject(obj[i]);       else           clone[i] = obj[i];   }   return clone; } Happy Coding !!  
Rated 4.0/5 based on 20 customer reviews
Normal Mode Dark Mode

Objects, object properties and object copy in Javascript

Tarun Sharma
Blog
15th Dec, 2017
Objects, object properties and object copy  in Javascript

Let’s talk simple things about object like adding properties, copy or deep copy object and Method defined for Object.

Objects in JavaScript, just as in many other programming languages, can be compared to objects in real life. The concept of objects in JavaScript can be understood with real life, tangible objects.

In JavaScript, an object is a standalone entity, with properties and type. Compare it with a cup, for example. A cup is an object, with properties. A cup has a color, a design, weight, a material it is made of, etc. The same way, JavaScript objects can have properties, which define their characteristics.

Objects and Properties

A JavaScript object has properties associated with it. A property of an object can be explained as a variable that is attached to the object. Object properties are basically the same as ordinary JavaScript variables, except for the attachment to objects.

Properties of JavaScript objects can also be accessed or set using a bracket notation (for more details see property accessors). Objects are sometimes called associative arrays, since each property is associated with a string value that can be used to access it. So, for example, you could access the properties of the myCar object as follows:

myCar['make'] = 'Ford';
myCar['model'] = 'Mustang';
myCar['year'] = 1969;

An object property name can be any valid JavaScript string, or anything that can be converted to a string, including the empty string.

Please note that all keys in the square bracket notation are converted to String type, since objects in JavaScript can only have String type as key type. For example, in the above code, when the key obj is added to the myObj, JavaScript will call the obj.toString()method, and use this result string as the new key.

You can also access properties by using a string value that is stored in a variable:

var propertyName = 'make';
myCar[propertyName] = 'Ford';
propertyName = 'model';
myCar[propertyName] = 'Mustang';

You can use the bracket notation with for...in to iterate over all the enumerable properties of an object. To illustrate how this works, the following function displays the properties of the object when you pass the object and the object's name as arguments to the function:

So, the function call showProps(myCar, "myCar") would return the following:

myCar.make = Ford
myCar.model = Mustang
myCar.year = 1969

Enumerate the properties of an object

Starting with ECMAScript 5, there are three native ways to list/traverse object properties:

1. for...in loops: This method traverses all enumerable properties of an object and its prototype chain

2. Object.keys(o): This method returns an array with all the own (not in the prototype chain) enumerable properties' names ("keys") of an object o.

3. Object.getOwnPropertyNames(o) : This method returns an array containing all own properties' names (enumerable or    not) of an object o.

Creating new objects

JavaScript has a number of predefined objects. In addition, you can create your own objects. You can create an object using an object initializer. Alternatively, you can first create a constructor function and then instantiate an object invoking that function in conjunction with the new operator.

Using object initializers

In addition to creating objects using a constructor function, you can create objects using an object initializer. Using object initializers is sometimes referred to as creating objects with literal notation. “Object initializer” is consistent with the terminology used by C++.

The syntax for an object using an object initializer is:

var obj = { property_1:   value_1,   // property_# may be an identifier...
          2:            value_2,   // or a number...
          // ...,
          'property n': value_n }; // or a string

Using a constructor function

Alternatively, you can create an object with these two steps:

1. Define the object type by writing a constructor function. There is a strong convention, with good reason, to use a capital initial letter.

2. Create an instance of the object with new.

3. To define an object type, create a function for the object type that specifies its name, properties, and methods. For example, suppose you want to create an object type for cars. You want this type of object to be called car, and you want it to have properties for make, model, and year. To do this, you would write the following function:

function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}

Notice the use of this to assign values to the object's properties based on the values passed to the function.

Now you can create an object called mycar as follows:

var mycar = new Car('Eagle', 'Talon TSi', 1993);

Using the Object.create method

Objects can also be created using the Object.create() method. This method can be very useful, because it allows you to choose the prototype object for the object you want to create, without having to define a constructor function.

Few Important methods:

  • Object.assign()

Copies the values of all enumerable own properties from one or more source objects to a target object.

  • Object.create()

             Creates a new object with the specified prototype object and properties.

  • Object.defineProperty()

             Adds the named property described by a given descriptor to an object.

  • Object.defineProperties()

             Adds the named properties described by the given descriptors to an object.

  • Object.entries()

             Returns an array of a given object’s own enumerable property [key, value] pairs.

  • Object.freeze()

             Freezes an object: other code can’t delete or change any properties.

Let's talk about Object Copy

The Naive Way of Copying Objects

The naive way of copying objects is looping through the original object and copying each property one after the other. Let’s take a look at this code:

Inherent Issues

1. ObjCopy object has a new Object.prototype method different from the mainObj object prototype method, which is not what we want. We want an exact copy of the original object.

2. Property descriptors are not copied. A “writable” descriptor with value set to be false will be true in the objCopy object.

3. The code above only copies enumerable properties of mainObj.

4. If one of the properties in the original object is an object itself, then it will be shared between the copy and the original making their respective properties point to the same object.

Shallow Copying Objects

An object is said to be shallow copied when the source top-level properties are copied without any reference and there exist a source property whose value is an object and is copied as a reference. If the source value is a reference to an object, it only copies that reference value to the target object.

A shallow copy will duplicate the top-level properties, but the nested object is shared between the original(source) and the copy(target).

Using Object.assign() method

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

In the code above, we changed the value of the property 'b' in objCopyobject to 80 and when we log the modified objCopy object in the console, the changes only apply to objCopy. The last line of code checks that the objobject is still intact and hasn't change. This implies that we have successfully created a copy of the source object without any references to it.

Pitfall of Object.assign()

Not so fast! While we successfully created a copy and everything seem to be working fine, remember we discussed shallow copying? Let’s take a look at this example:

Why is obj.b.c = 30? we have problem here

Note: Properties on the prototype chain and non-enumerable properties cannot be copied. See here:

Deep copy of object

A deep copy will duplicate every object it encounters. The copy and the original object will not share anything, so it will be a copy of the original. Here’s the fix to the problem we encountered using Object.assign().

Let's explore another option to fix this.

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

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. Here's an example:

Another Way is Deep clone

function cloneObject(obj) {
  var clone = {};
  for(var i in obj) {
     if(obj[i] != null &&  typeof(obj[i])=="object")
          clone[i] = cloneObject(obj[i]);
      else
          clone[i] = obj[i];
  }
  return clone;
}

Happy Coding !!

 

Tarun

Tarun Sharma

Blog Author

Tarun Sharma is a J2EE Enterprise application developer, working on Enterprise and open source Technologies J2EE web frameworks, Spring, Spring MVC, Struts, Hibernate, Web service Jax-WS, Jax-RS and having experience of working Enterprise SOA architecture and different tools from IBM and Oracle. Currently, working with JavaScript framework Angular Node js and exploring development of enterprise apps in Android.

Leave a Reply

Your email address will not be published. Required fields are marked *

SUBSCRIBE OUR BLOG

Follow Us On

Share on

other Blogs