Concepts of Object — Part 1

Image for post
Image for post

📄 Table of Contents

  • What are objects?
  • how to access object properties ?
  • Delete a property from an object
  • ‘4’ ways to Create objects in JavaScript
  • Get Keys / values / Entries of Object
  • Merge Two Objects
  • Prevent Modification to an Existing Object
  • Clone Objects

▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬ ✦ ✦ ✦ ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬

◉ What are Objects ?

An object in JavaScript is a collection of key-value pairs. Each key-value pair is called as a property.

A property can be a function, an array, an object itself or any primitive data type i.e. integer, string, etc.

Functions in object are called as methods.

Example:

var human = {
firstName: "Anil",
lastName: "Kumar",
age: 30,
fullName: function(){
return this.firstName + " " + this.lastName
}
}

Here, firstName, lastName, and fullName are properties of the same object i.e. human. firstName is the key and Anil is the value of the property.

◉ Properties of the object can be accessed using the following two notations:

[1]. Dot notation:

human.firstName;   //Output: Anil
human.fullName(); //Output: Anil Kumar

New properties can be added using the dot notation as shown below:

human.age = 27
human.getAge = function(){
return this.age;
}

[2]. Square bracket notation:

human["firstName"]; //Output: Anil
human["fullName"](); //Output: Anil Kumar

New properties can be added using the Square bracket notation as shown below:

human["weight"] = 68
human.getWeight = function(){
return this.weight;
}

Properties can also be accessed using a variable having value equal to the property name as shown below:

var firstNameProperty = "firstName";console.log(human[firstNameProperty]) // Output: Anil

Note: Above method of using variable to access property names cannot be used to access properties of the object using dot notation.

Console.log(human.firstNameProperty) //Output: undefined

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

However, any property name that is NOT a valid Javascript identifier (for example, a property name that has a space or a hyphen, or that starts with a number) can only be accessed and added to the object property using the square bracket notation

human["date of birth"] = "Nov 28";
human[12] = 12;
human.12 = 12; //gives error

console.log(human.12); //Gives error
console.log(human[12]); //Output: 12

◉ Delete a property from an object

To delete a property from an object we can use the delete operator.

You cannot delete properties that were inherited, nor can you delete properties with their attributes set to configurable.

‘delete’ operator returns true if the delete was successful. It also return true if the property to delete was non-existent or the property could not be deleted.

delete human.firstName; // return true

Let’s see what happens if we try to call fullName method which uses both the firstName and lastName property of human object.

console.log(human.fullName());// undefined Anil

Output is undefined because we were trying to access firstName property of human object which does not exists.

◉ ‘4' ways to Create objects in JavaScript

[1]. Object literal

[2]. new Object() syntax

[3]. Object Constructor + new

[4]. Object.create()

[1]. Using Object literal

There is NO requirement for a class as such and can be declared using literal notation like below:

var human = {
firstName: "Anil",
lastName: "Kumar",
age: 30,
fullName: function(){
return this.firstName + " " + this.lastName
}
}

[2]. Using new Object() syntax

var human = new Object()
console.log(human);// Creates an empty object

Creating objects using new Object() and object literal does the same thing. For simplicity, readability and execution speed, use object literal.

We can add new properties and methods to the above objects using the dot and/or square notation.

However, the above method using new Object() is NOT well suited to programs that require the creation of multiple objects of the same kind, as it would involve repeatedly writing the above lines of code for each such object.

To deal with this problem, we can use the next method.

[3]. Object Constructor + new

This comes in handy when we need to create an object “type” that can be used multiple times without having to re-define the object every time.

Constructor function in JavaScript is used for creating new objects using a blueprint. Just like classes are used for creating objects in Java, C# we can use constructors to create objects in JavaScript.

Objects can be created using the constructor function syntax using the following two steps:

  1. Define the object blueprint(class) by defining the constructor function. By convention, name of the constructor function should start with CAPITAL letter
  2. Create the object by instantiating the constructor function using new operator. JavaScript lets you define objects that can be instantiated like a class with the new keyword.

Example:

function Human(firstName, lastName) {
this.firstName = firstName,
this.lastName = lastName,
this.fullName = function() {
return this.firstName + " " + this.lastName;
}
}

var person1 = new Human("Anil", "Kumar");

console.log(person1)

This is just the blueprint. To create the object we will use the new operator.

var ak = new Human("Anil", "Kumar");
var kk = new Human("Kabir", "Khan");

Since ES6, you can define an object as an instance of a class.

For example:

class Human{
constructor(firstName, lastName){
this.firstName = firstName,
this.lastName = lastName
}
}
Human.prototype.fullName = function() {
return this.firstName + " " + this.lastName;
}
const ak = new Human("Anil", "Kumar");

Problem with creating objects with the constructor function:

Consider the constructor function below:

Let’s create objects person1 and person2 using the Human constructor function:

var person1 = new Human("Virat", "Kohli");
var person2 = new Human("Sachin", "Tendulkar");

On executing the above code, the JavaScript engine will create two copies of the constructor function, each for person1 and person2.

Image for post
Image for post

i.e. every object created using the constructor function will have its own copy of properties and methods. It doesn’t make sense to have two instances of function fullName that do the same thing. Storing separate instances of function for each object results in wastage of memory. We will see as we move forward, how we can solve this issue.

[4]. Object.create()

Image for post
Image for post
Image for post
Image for post

The Object.create method is also one of the methods to create a new object in JavaScript. This method creates a new object with the specified prototype and properties of the old object.

Note: Every JavaScript function has a prototype property which is empty by default. We may attached methods or properties to prototype.

// syntax — Object.create(prototype[, propertiesObject])var newStudent = Object.create(student); // this create a new object with old object added in its prototype // chain

Below is the output of the object and prototype key (__proto__).

Image for post
Image for post

Basic syntax:

Object.create(prototype_object, propertiesObject)

Object.create method accepts two arguments as:

  1. prototypeObject: newly created objects prototype object. It has to be an object or null.
  2. propertiesObject: Properties of the new object. This argument is optional

Create an object with Object.create with no prototype

Consider the below example to create a new object in JavaScript

var person = Object.create(null);

typeof(person) // Object
console.log(person) // Object with prototype object as null

// Set property to person object
person.name = "Anil";

console.log(person)
// Object with name as property and prototype as null
Image for post
Image for post

Here, we have created a new object person using Object.create method. As we have passed null for the prototypeObject. person object does not have any prototype object.

Further, we have added name as new property to the person object.

Create object with prototype:

prototypeObject = {
fullName: function(){
return this.firstName + " " + this.lastName
}
}
var person = Object.create(prototypeObject)

console.log(person)
// Object with prototype object as prototypeObject and no properties

// Adding properties to the person object
person.firstName = "Virat";
person.lastName = "Kohli";

person.fullName() // Virat Kohli

Console output:

Image for post
Image for post

In the above example, we have created a prototypeObject with fullName function. We created a person object with prototypeObject as prototype object of the person’s object using Object.create(). Further we added firstName and lastName properties to the person object. Here, we have added firstName and lastName properties after the object creation. It would have been great if we could add these properties while creating the object. To do that, we will use the 2nd argument of Object.create method.

Object.create 2nd argument — propertiesObject

propertiesObject is used to create properties on new object. It acts as a descriptor for the new properties to be defined. Descriptors can be data descriptor or access descriptors.

Data descriptors are

  1. configurable
  2. enumerable
  3. value
  4. writable

Access descriptors are

  1. get
  2. set

In detail, descriptors can be read here

Example:

prototypeObject = {
fullName: function(){
return this.firstName + " " + this.lastName
}
}

var person = Object.create(prototypeObject, {
'firstName': {
value: "Virat",
writable: true,
enumerable: true
},
'lastName': {
value: "Kohli",
writable: true,
enumerable: true
}
})

console.log(person)
// Object with prototype object as prototypeObject and properties as firstName and lastName
Image for post
Image for post

In the above example we have created a new object person with prototype object as prototypeObject and properties as firstName and lastName.

Properties firstName and lastName have been added using the 2nd parameter of the Object.create().

◉ Inheritance using Object.create()

Read Inheritance in JavaScript before reading the below part.

//SuperType constructor function
function SuperType(firstName, lastName){
this.firstName = "Virat",
this.lastName = "Kohli"
}

//SuperType prototype
SuperType.prototype.getSuperName = function(){
return this.firstName + " " + this.lastName;
}

//SubType prototype function
function SubType(firstName, lastName, age){
//Inherit instance properties
SuperType.call(this, firstName, lastName);
this.age = age;
}

SubType.prototype = Object.create(SuperType.prototype)

// Make sure this is created after the above line otherwise, above line will override this prototype object and this function will not be present
SubType.prototype.getSubAge = function() {
return this.age;
}

//Create SubType objects
var subTypeObj1= new SubType("Virat", "Kohli", 26);

//subTypeObj1
console.log(subTypeObj1.firstName); //Output: Virat
console.log(subTypeObj1.age); //Output: 26
console.log(subTypeObj1.getSuperName()); //Output: Virat Kohli
console.log(subTypeObj1.getSubAge()); //Output: 26

console.log(subTypeObj1 instanceof SubType) // Output: true
console.log(subTypeObj1 instanceof SuperType) // Output: true

Here we have copied the prototype of the SuperType to the SubType.prototype using Object.create method. Rest everything is same as the inheritance in JavaScript.

source: https://medium.com/better-programming/how-to-do-common-javascript-object-operations-b2e121233ec6

◉ Get Keys of Object

Object.keys can be used to get all the top level keys of an object as strings. For example:

const chicken = { hasWings: true, bodyParts: [ {head: 1} ]};
console.log(Object.keys(chicken)) // ['hasWings', 'bodyParts'];

Get Entries of an Object

Object.entriescan be used to get all the top level keys-value entries of an object as arrays. For example:

const chicken = { hasWings: true, bodyParts: ['head', 'tail']};
console.log(Object.entries(chicken))
// [['hasWings', true], ['bodyParts', ['head', 'tail']]];

◉ Merge Two Objects

We can use the spread operation to combine two objects into one.

const a = {foo: 1};
const b = {bar: 1};
const c = {...a, ...b};
// {foo: 1, bar: 1}

If two objects have the same keys, the value of the one that is merged in last will override the earlier one.

const a = {foo: 1};
const b = {bar: 1};
const c = {bar: 2};
const d = {...a, ...b, ...c};
console.log(d) // {foo: 1, bar: 2}

◉ Prevent Modification to an Existing Object

Object.freeze can be used to prevent an object from being modified. freeze takes an object as its argument and freezes an object in place.

For example:

let a = {foo: 1};
a.foo = 2;
Object.freeze(a);
a.foo = 3;
console.log(a) // {foo: 2}

Check If an Object Can Be Modified

Object.isFrozen can be used to check if an object is frozen by Object.freeze .

For example:

let a = {foo: 1};
a.foo = 2;
Object.freeze(a);
a.foo = 3;
console.log(Object.isFrozen(a)) // true
Image for post
Image for post

◉ Cloning Objects (Shallow vs Deep copy)

If you assign an object to another variable, it just assigns the reference to the original object, so both variables will point to the original object. When one of the variables are manipulated, both will be updated. This is not always the desired behaviour. To avoid this, you need to copy an object from one variable to another. In JavaScript, this is easy to do.

[1]. Object.assign()

To shallow copy an object, we can use Object.assign(), which is built into the latest versions of JavaScript. This function does a shallow copy, which means it only copies the top level of an object, while the deeper levels remain linked to the original object reference. This may NOT be desired if there is nested in your original object.

Here is an example of how to use Object.assign :

const a = { foo: {bar: 1 }}
const b = Object.assign({}, a)
// get a clone of a which you can change with-out modifying a itself
b.foo.bar = "999";
console.log(a.foo.bar);
# 999

You can also clone an array like this:

const a = [1,2,3]
const b = Object.assign([], a)
// get a clone of a which you can change with out modifying a itself

Shallow cloning does not copy nested objects. So if obj contains an object name, Object.assign() will keep a reference to the original copy of name rather than creating a copy of name.

Image for post
Image for post

Generally, to deep clone an object, you need a library like Lodash. There is an alternative though to do a deep copy of a object without a library, you can JSON.stringify then JSON.parse :

const a = { foo: {bar: 1, {baz: 2}}
const b = JSON.parse(JSON.stringify(a))
// get a clone of a which you can change WITHOUT modifying a itself

This does a deep copy of an object, which means all levels of an object are cloned instead of referencing the original object.

Image for post
Image for post

However, this approach only works well if your object only contains strings, numbers, booleans, objects, and arrays. For example, if your object has a property date that is a JavaScript date, the cloned object’s date property will be a string, because that’s how JSON.stringify() serializes dates.

Image for post
Image for post

[2]. DE-structuring

With ES6, you can also use object DE-structuring to shallow clone objects, like so:

const orig = { foo: 
{bar: 1}
}; // nested object
const copy = {...orig}; // get a clone of orig which you can change with out modifying orig itselfcopy.foo.bar = "999";
console.log(orig.foo.bar); # "999"

References:

source: https://medium.com/@happymishra66/objects-in-javascript-2980a15e9e71

source: https://medium.com/@happymishra66/create-objects-in-javascript-10924cfa9fc7

Experience with Front-end Technologies and MERN / MEAN Stack. Working on all Major UI Frameworks like React, Angular.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store