Image for post
Image for post

📄 Table of Contents

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

◉ “4” Pillars of Inheritance

Abstraction, Encapsulation, Inheritance and Polymorphism are the four pillars of Object Oriented Programming.

It is the method of hiding the unwanted information. It means hiding the inner implementation details and showing only outer details.

In jQuery, we will use $(“#elem”) to select an element with id `elem` on a web page. Actually this code calls native JS code.

document.getElementById("elem")

but we don’t need to know & can happily use the $(“#elem”) without knowing inner details of the implementation.

Encapsulation is a method to hide the data in a single entity (Wrapping up of public and private data into a single data unit) along with a method to protect information from outside.

Encapsulation can be implemented using by access modifier i.e. private, protected and public.

function Person() { // private variables
var dob = "21-09-1988";
//public properties and methods
return{
age: "30",
name: "ak",
getDOB: function () {
return dob;
}
}
}
var foo = new Person();
console.log(foo.dob); # undefined
console.log(foo.getDOB()); # 21-09-1988

It means having more than one form.

In JS, an object, property, method can have more than one form. Polymorphism is a very cool feature for dynamic binding and late binding.

◉ Inheritance

Unlike all other object-oriented programming languages, JavaScript chose prototypes for its way of handling inheritance, but with the release of ES2015, classes were introduced to the language’s syntax.

Let me put light on thought:

Classes are just syntactic sugar, JavaScript still remains prototype based. They are not a new object-oriented inheritance model.

Javascript follows the prototype mechanism to inherit properties and methods.

When we call the property or method of an object, the browser checks to see if the actual object has the method on it, if NOT it checks if the method is available to it through its prototype object.

Image for post
Image for post

We create sportsCar and provide properties of brandName, topSpeed, and color. Then we added a property called gearType to the Car prototype object and assigned the value ‘automatic’ to it.

When we call any defined object property, it will give you the value because it is available in the object itself, and when we call gearType it will also give you the value but, the only difference is it is available in the objects constructor prototype.

But if we check if either sportsCar.hasOwnProperty(‘gearType’) and Car.hasOwnProperty(‘gearType’) of ‘gearType’ and both return false, but Car.prototype.hasOwnProperty(‘gearType’) return true.

That is a Javascript prototype-based inheritance.

Image for post
Image for post
source: Source: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance

OR

Father.call(this);

Note that we’ve only specified “this” inside call() — no other parameters are required as we are not inheriting any properties from the parent that are set via parameters.

◉ JavaScript Inheritance with “Object.create”

Using “Object.create” is the most basic way to create an Inheritance Model in JavaScript. Object.create can be used to create new object using the existing object as a prototype. The existing object is made available as prototype making all the properties of existing Object available to the new Object.

Let’s see this method in Details.

In the above code, we are using “Object.create”, to create a new Object. Since we haven’t adding any property or Method to the new Object therefore the Object “newObject” is still empty having no method or properties.

See the image below.

Image for post
Image for post

The output above shows that none of the property is available to the newly created object. It still do not contain any method or properties.

But, we are passing “userInfo” object to “Object.create” function as a parameter. “userInfo” Object contains “name”, “age”, “designation” and “salary” property along with their values. Let’s look into the impact of passing “userInfo” as a parameter to the function.

YES, we can 100%.

When we create Object using “Object.create”, the Object passed as parameter is added to the “prototype” chain of the newly created Object. When user try to access the property from the new Object created, it looks for the prototype chain available to the new Object. The JavaScript Object can traverse “prototype” chain using “__proto__” property.

The “userInfo” object passed to Object.create function was added to “__proto__” property of the new Object.

Let’s see how can we access this prototypal chain of the Object.

Image for post
Image for post

When we try to access the property “name” using “newObject”, it first looks for the properties that are available to this Object. Since we do not have any property added to this Object, it traverses to the “prototype” chain using the Object reference “__proto__”. The “__proto__” property points to the reference of “userInfo” object.

Image for post
Image for post

Since the properties “name” is available in the Object which is pointed by “__proto__” property, we can access the property “name” using the newly created Object. The properties “name”, “age”, “designation” and “salary” is available to the new Object using the prototypal chain.

In short, it represents the Parent Child relationship, if the property in not found in an Object being referred, it traverses its prototype chain to find the property/method in the Parent Object. If the property/method is available in the Prototype Chain, we can access those property and methods.

Image for post
Image for post

The above lines of code, we are using “===”, it state that “userInfo.name” and “newObject.__proto__name” point to the same memory location.

Till now, we have talked about accessing the properties from the Prototype Chain. We can also access the methods available in the prototype chain. Let’s look with the help of an example.

“name” property is available in the Prototype Chain of the newly created Object. We can add the property with the same name to the new Object. When we add the property with the same name to the new Object, it gets added to the property of new Object. If the user tries to access/modify the “name” property, it refers to the property added to the Object, rather than accessing the name property from the prototype chain.

In the above code, we can see that, we are adding the property to the newly created Object. In this case the Object will be having a new property available to itself and it will access/modify its own property, rather than referring to the parent property.

Image for post
Image for post

In the image above, we can see that the “name” property is added to the newly created Object “newObject”.

Lets look into Advantages and Disadvantages of this Method:

  1. All the methods and Properties which are available to the “userInfo” object is available to the new Object that is created, since it exists as the part of prototypal Chain. We can use this method and take advantage of function and property re-usability.
Image for post
Image for post

The Property is made available through the prototypal chain, so the object need not to consume more memory space to save the existing Functions and Properties. No separate memory space is consumed. So the methods and the properties can be reused.

This method provides function and property re-usability in cases when we have some hierarchical data representation / or if we need to show some inheritance traits from Source Object to Destination Object

  1. The newly created Object do NOT create a separate property. Modifying the property from the Source Object, modifies the data available to the new Object also.

The developer may assume that the property belongs to the new Object created. Whereas, modifying the property or Function in Source Object are reflected in Destination/new Object Created.

Image for post
Image for post

If you want to have dedicated ”name” property to each Object created using “Object.create”, we need to add property explicitly to newly created Object. In the below code, we have added separate property to the new Object Created, So in this case it will not access the “name” data from Prototype Chain.

2. Do not create the Deep Copy for the Object

It do not create the Deep copy, the Object follow the Concept of Inheritance. So the new Object do not contains separate properties and methods. The properties and methods are accessed from the parent in the Inheritance Chain.

Object.create() Exercises

Object.create() Exercise
Object.create() Exercise
Image for post
Image for post

Let’s understand how this works, internally extends keyword works using the prototype mechanism.

class Son extends Father this will get converted into the prototype object i.e. 
Son.prototype.__proto__ will be Father.prototype

In our case: Son.prototype.__proto__ = Father.prototype

So if the method is not found in Son class, Javascript takes it from the Father class.

Javascript is prototype-based only, in class inheritance also, it works on top of prototypal inheritance (mechanism).

With constructors it gets a little bit tricky.

Let’s say Son (derived class) doesNot have any constructor rather inheriting from Father (parent class).

According to the specification, if a class extends another class and has no constructor, then the following “empty” constructor is generated:

Image for post
Image for post
Derived Class with no constructor of its own

Prototypal inheritance may take some time getting used to, but it’s an important concept to grasp in order to master OOP in vanilla JavaScript. While it is often considered to be one of JavaScript’s weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic inheritance model on top of a prototypal model.

ECMAScript 6 introduced a new set of keywords implementing classes. Although these constructs looks like class-based languages, they are not the same. JavaScript remains prototype-based.

◉ Composition over Inheritance (recommended in React)

Image for post
Image for post
Composition is recommended over Inheritance in React

◉ Private Members in JavaScript

JavaScript is the world’s most misunderstood programming language. Some believe that it lacks the property of information hiding because objects cannot have private instance variables and methods. But this is a misunderstanding. JavaScript objects can have private members. Here’s how.

JavaScript is fundamentally about objects. Arrays are objects. Functions are objects. Objects are objects. So what are objects? Objects are collections of name-value pairs. The names are strings, and the values are strings, numbers, booleans, and objects (including arrays and functions). Objects are usually implemented as hashtables so values can be retrieved quickly.

If a value is a function, we can consider it a method. When a method of an object is invoked, the this variable is set to the object. The method can then access the instance variables through the this variable.

Objects can be produced by constructors, which are functions which initialize objects. Constructors provide the features that classes provide in other languages, including static variables and methods.

➪ Public

The members of an object are all public members. Any function can access, modify, or delete those members, or add new members. There are two main ways of putting members in a new object:

This technique is usually used to initialise public instance variables. The constructor’s this variable is used to add members to the object.

function Container(param) {
this.member = param;
}

So, if we construct a new object

var myContainer = new Container('abc');

then myContainer.member contains ‘abc’.

This technique is usually used to add public methods. When a member is sought and it isn’t found in the object itself, then it is taken from the object’s constructor’s prototype member. The prototype mechanism is used for inheritance. It also conserves memory. To add a method to all objects made by a constructor, add a function to the constructor’s prototype:

Container.prototype.stamp = function (string) {
return this.member + string;
}

So, we can invoke the method

myContainer.stamp('def')

which produces ‘abcdef’.

Private and privileged members can only be made when an object is constructed.

Public members can be added at any time.

➪ Private

Private members are made by the constructor. Ordinary vars and parameters of the constructor become the private members.

function Container(param) {
this.member = param;
var secret = 3;
var that = this;
}

This constructor makes three private instance variables: param, secret, and that. They are attached to the object, but they are not accessible to the outside, nor are they accessible to the object’s own public methods. They are accessible to private methods.

Private methods are inner functions of the constructor.

function Container(param) {

function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}

this.member = param;
var secret = 3;
var that = this;
}

The private method dec examines the secret instance variable. If it is greater than zero, it decrements secret and returns true. Otherwise it returns false. It can be used to make this object limited to three uses.

By convention, we make a private that variable. This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions.

Private methods cannot be called by public methods.

To make private methods useful, we need to introduce a privileged method.

➪ Privileged

A privileged method is able to access the private variables and methods, and is itself accessible to the public methods and the outside. It is possible to delete or replace a privileged method, but it is not possible to alter it, or to force it to give up its secrets.

Privileged methods are assigned with this within the constructor.

function Container(param) {

function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}

this.member = param;
var secret = 3;
var that = this;

this.service = function () {
return dec() ? that.member : null;
};
}

service is a privileged method. Calling myContainer.service() will return ‘abc’ the first three times it is called. After that, it will return null. service calls the private dec method which accesses the private secret variable. service is available to other objects and methods, but it does not allow direct access to the private members.

Closures

This pattern of public, private, and privileged members is possible because JavaScript has closures. What this means is that an inner function always has access to the vars and parameters of its outer function, even after the outer function has returned. This is an extremely powerful property of the language. It is described in How JavaScript Works.

Patterns

function Constructor(...) {
this.membername = value;
}
Constructor.prototype.membername = value;
function Constructor(…) {
var that = this;
var membername = value;
function membername(…) {…}
}

Note: The function statement

function membername(...) {...}

is shorthand for

var membername = function membername(...) {...};
function Constructor(...) {
this.membername = function (...) {...};
}

References:

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