OBJECTS in js
June 07, 2020
In this blog, I will try to cover the concept of objects in javaScript in detail. After reading this blog I am sure you will have a clear understanding of the topic. Let's get started…
Introduction.
Object in javaScript is just a collection of key-value pair. A key can be considered as a unique name for every value so that we can access them. Values can be either a primitive data type or they can be a function or another object. These key-value pairs are called as properties or methods depending on the type of value.
Let’s take an example :
Here a person is an object. It has two properties called name, age and one method called greets. Here name, age, greets belongs to the person object and we can access them in the following way.
| let person = { | |
| name : "Rahul", | |
| age : 20 , | |
| greets : function (){ | |
| console.log("Hi, I am Rahul") | |
| } | |
| } | |
| // Accessing the object | |
| console.log(person.name) //Output : "Rahul" | |
| console.log(person.age) //Output : 20 | |
| console.log(person.greets()) //Output : "Hi, I am Rahul" |
We can also access objects using square bracket notation
| // Accessing the object using square bracket notation | |
| console.log(person.['name']) //Output : "Rahul" | |
| console.log(person.['age']) //Output : 20 | |
| console.log(person.['greets']()) //Output : "Hi, I am Rahul" |
Note : Square bracket notation is used incase we want to access properties dynamically
Creating objects in javaScript
There are various methods of creating an object but we will focus on the following three :
Direct method :
We have seen this in above examle
| let person = { | |
| name : "Rahul", | |
| age : 20 , | |
| greets : function (){ | |
| console.log("Hi, I am Rahul") | |
| } | |
| } | |
| console.log(typeOf(person)) | |
| //Output : Object |
Using a function constructor :
| function Animal(name,type,voice){ | |
| const color = "something" ; | |
| this.name = name ; | |
| this.type = type ; | |
| this.sound = function () { | |
| console.log(voice) ; | |
| } | |
| } | |
| // Creating an Object using constructor function | |
| const Tiger = new Animal('Tiger','mammal','roar...') | |
| console.log(Tiger) //Output : Animal {name: "Tiger", type: "mammal", sound: ƒ} | |
| console.log(Tiger.sound()) //Output : roar... |
This is dynamic way for creating javaScript objects.
Animal() is just a simple js function which acts as a constructor for Tiger object. Notice how 'this' keyword is used here, it is used to create properties and methods for Tiger object.
The 'new' keyword creates an empty object. 'this' keyword in Animal function references to that empty object.
If we simply declare some variable in Animal() our code will not throw any error, but that variable will not become a property of object.
For eg. in our case observe that color is not a property of the Tiger object.
Arrow functions can’t be used as a function constructor
Always the first letter of function constructor name should be capital according to convention
The Arguments in Animal function can be used to pass values to object dynamically.
This is a dynamic way of creating an object in js.
Using ES6 class concept :
| class Animal { | |
| constructor(name,type,voice){ | |
| this.name = name ; | |
| this.type = type ; | |
| this.sound = function () { | |
| console.log(voice) ; | |
| } | |
| } | |
| } | |
| // Let's create an object using Animal class | |
| const Tiger = new Animal('Tiger','mammal','roar...') | |
| console.log(Tiger) //Output : Animal {name: "Tiger", type: "mammal", sound: ƒ} | |
| console.log(Tiger.sound()) // Output : roar... |
Here we are creating a class named Animal. All the properties and methods which we want to assign to object are placed inside the class constructor.
The constructor receives arguments which we have passed while object creation.
A JavaScript class is declared with a PascalCase in contrast to other JavaScript data structures ie. first letter in every word should be capital. Eg ; class AnimalKingdom
Make sure you use you call super() method inside the constructor() method if the current object extends some other object, this is done so that we can use properties and method of parent class.
Mutability of js objects
Primitive data types like number, boolean and strings are Immutable whereas objects in js are mutable in nature. Mutability means that we can edit the values after it is assigned. Let’s look at a simple example which will make things clear.
| let name1 = 'Rahul' ; | |
| let name2 = name1 ; | |
| name2 = 'Ramesh' | |
| console.log(name1) //Output : Rahul | |
| console.log(name2) //Output : Rahul |
In above code snippet variable name1 contains a string - ‘Rahul’
On second line we are saying that assign value in name1 to name2. So here the value gets copied and if we change variable name2 then, name1 don’t gets affected.
which is obvious
but objects don't exhibit such behaviour,
| let person1 = { | |
| name : 'Rahul' | |
| } | |
| let person2 = person1 ; | |
| // updating person2 | |
| person2.name = "Ramesh" | |
| console.log(person1) // Output : {name: "Ramesh"} | |
| console.log(person2) // Output : {name: "Ramesh"} | |
| // Why do this happen? |
In case of objects, person1 variable holds the address to memory location where the object data is stored and when we assign person1 to person2 this address gets copied into person2 variable.
Therefore now making changes in person2 will also affect person1 object.
Lets take one more example :
| let person1 = { | |
| name : 'Rahul' | |
| } | |
| let person2 = person1 ; | |
| // Case 1 | |
| if(person1 === person2){ | |
| console.log(true) | |
| } | |
| else{ | |
| console.log(false) | |
| } | |
| let person3 = { | |
| name : 'Rahul' | |
| } | |
| let person4 = { | |
| name : 'Rahul' | |
| } | |
| // Case 2 | |
| if(person3 === person4){ | |
| console.log(true) | |
| } | |
| else{ | |
| console.log(false) | |
| } |
In case 1 answer will be true because both variable contains same address and on comparison answer will be true.
On the other hand Case 2 output will be false. This is because even though person3 and person4 have the same content inside they are stored on different memory location and above two variable only contains their addresses.
Now you must be wondering how to compare two objects? How to find whether objects received from two different sources have the same properties and methods?
Actually there is no direct way because the variable stores the address to the memory locations and the content inside that memory location is not evaluated,
But don’t worry there is one hack though…
We can Convert the objects which we want to compare in string format using JSON.stringify() method. Store those values and compare them using equality operator. And now the output will be true
| const k1 = { fruit: 'Kiwi' }; | |
| const k2 = { fruit: 'kiwi' }; | |
| // Using JavaScript | |
| if(JSON.stringify(k1) === JSON.stringify(k2)){ | |
| console.log(true) ; | |
| } | |
| else{ | |
| console.log(false) ; | |
| } | |
| // Output : True |
Working with objects :
Here are some of the methods which can be uselful while working with objects..
- Object.create() : The Object.create() method creates a new object, using an existing object as blueprint.
| const person = { | |
| isHuman: false, | |
| printIntroduction: function() { | |
| console.log(`My name is ${this.name}.`); | |
| } | |
| }; | |
| const me = Object.create(person); | |
| me.name = 'Rahul'; // "name" is a property set on "me", but not on "person" | |
| me.isHuman = true; // inherited properties can be overwritten | |
| me.printIntroduction(); |
- object.keys() : The Object.keys() method returns an array of a given object's own enumerable property names, iterated in the same order that a normal loop would.
| const object1 = { | |
| a: 'somestring', | |
| b: 42, | |
| c: false | |
| }; | |
| console.log(Object.keys(object1)); | |
| // expected output: Array ["a", "b", "c"] |
- object.assign() : The Object.assign() method copies all enumerable own properties from one or more source objects to a target object. It returns the target object. //Object.assign(target, ...sources)
| const target = { a: 1, b: 2 }; | |
| const source = { b: 4, c: 5 }; | |
| //there can be multiple sources | |
| const returnedTarget = Object.assign(target, source); | |
| console.log(target); | |
| // expected output: Object { a: 1, b: 4, c: 5 } | |
| console.log(returnedTarget); | |
| // expected output: Object { a: 1, b: 4, c: 5 } |
- object.freeze() : The Object.freeze() method freezes an object. A frozen object can no longer be changed; freezing an object prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. In addition, freezing an object also prevents its prototype from being changed. freeze() returns the same object that was passed in.
- The Object.seal() method seals an object, preventing new properties from being added to it and marking all existing properties as non-configurable. Values of present properties can still be changed as long as they are writable.
| let person = { | |
| name : "Rahul", | |
| age : 20 , | |
| greets : function (){ | |
| console.log("Hi, I am Rahul") | |
| } | |
| } | |
| Object.seal(person) ; // seals the object | |
| Object.freeze(person) ; // freezes the object |