JavaScript ~ Object Oriented Programming - rohit120582sharma/Documentation GitHub Wiki

Inheritance

JavaScript has a prototype-based inheritance mechanism.

Inheritance is a programming paradigm where objects (or Classes in some languages) can inherit properties and methods from other objects (or Classes).

Every object in Javascript has a prototype. When a messages reaches an object, JavaScript will attempt to find a property in that object first, if it cannot find it then the message will be sent to the object’s prototype and so on. This works just like single parent inheritance in a class based language.



prototype chain


The prototype property

Every JavaScript function has a special property called prototype.

prototype property which is an empty object by default.

This property is used primarily for inheritance; you add methods and properties on a function’s prototype property to make those methods and properties available to instances of that function.

When a function is used as a constructor and called with the new keyword. It creates an instance object with proto property which points to function’s prototype object. So prototype property is used to build proto when the function happens to be used as a constructor with the new keyword.

prototype property is not enumerable.


The proto object

To understand prototype chains in JavaScript there is nothing as simple as the proto property.

The proto is the actual object that is used in the lookup chain to resolve variables or methods. It is a property that all objects have. This is the property which is used by the JavaScript engine for inheritance.



Object Creation

Object literal

Object.create()

Create an empty JavaScript object

It is an awesome utility for prototype creation

Provide a bonus feature which makes a link up to shared functions (an object full of functions) passed in as an argument. In other words, assign that object to hidden proto property of newly created object

It is JavaScript prototypal nature which means when JavaScript doesn’t find the method directly on the object, it looks on hidden proto property


Creating objects with function

A normal function that is used to construct objects and you use the new keyword to call the constructor.

When you call a function with new, following things happen under the hood:

  • Creates a new (empty) object
  • Gets the prototype of the constructor function and sets it as the prototype of the new object
  • Invoke the constructor function which creates a new execution context along with this property
  • Set new object as a value of this property
  • Execute all statements line by line from the function
  • Returns the new object

Creating objects with class

JavaScript class is (mostly) just syntactical sugar for prototypes, which are very different from traditional classes.



Subclassing

Subclassing with Factory function

It does 3 following things:

  • Create an empty object with Object.create()
  • Assign set of shared functions to proto property
  • Return the newly created object
// Super Class
function userCreator(_name, _score) {
	const newUser = Object.create(userFunctions);
	newUser.name = _name;
	newUser.score = _score;
	return newUser;
}
const userFunctions = {
	sayName: function() {
		console.log('I am ' + this.name);
	},
	increment: function() {
		this.score++;
	}
};

const user1 = userCreator('Rohit', 4);
user1.sayName(); // I am Rohit

// Sub Class
function PaidUserCreator(_name, _score, _accountBalance) {
	const newPaidUser = userCreator(_name, _score);
	Object.setPrototypeOf(newPaidUser, paidUserFunctions);
	newPaidUser.accountBalance = _accountBalance;
	return newPaidUser;
}
const paidUserFunctions = {
	increaseBalance: function() {
		this.accountBalance++;
	}
};

Object.setPrototypeOf(paidUserFunctions, userFunctions);

const paidUser1 = new PaidUserCreator('Anubha', 4, 25);
paidUser1.sayName(); // I am Anubha
paidUser1.increaseBalance();

Subclassing with new & call

It does 3 following things implicitly:

  • Create an empty JavaScript object and assign to this variable
  • Set PaidUserCreator.prototype to proto property
  • Return this
// Super Class
function UserCreator(_name, _score) {
	this.name = _name;
	this.score = _score;
}
UserCreator.prototype.sayName = function() {
	console.log('I am ' + this.name);
}
UserCreator.prototype.increment = function() {
	this.score++;
}

const user1 = new UserCreator('Rohit', 4);
user1.sayName(); // I am Rohit

// Sub Class
function PaidUserCreator(_name, _score, _accountBalance) {
	UserCreator.call(this, _name, _score);
	this.accountBalance = _accountBalance;
}
PaidUserCreator.prototype = Object.create(UserCreator.prototype);
PaidUserCreator.prototype.increaseBalance = function() {
	this.accountBalance++;
}
const paidUser1 = new PaidUserCreator('Anubha', 4, 25);
paidUser1.sayName(); // I am Anubha
paidUser1.increaseBalance();

Subclassing with class, extends & super

Terminology

The extends does two things:

  • Set PaidUserCreator.prototype.__proto__ = UserCreator.prototype
  • Set PaidUserCreator.__proto__ = UserCreator

The super uses Reflect.construct() under the hood. The static Reflect.construct() method acts like the new operator, but as a function. It is equivalent to calling new target(...args).

Calling sub-class does following things:

  • Call constructor() function
  • Calling super()
    • Call new UserCreator() by referring to PaidUserCreator.proto
      • Create an empty JavaScript object and assign to this variable
      • Set proto property to PaidUserCreator.prototype object
      • Return this
    • Replaced with this returned from new UserCreator()
  • Create this in PaidUserCreator.constructor and assigned to result of super() call
  • Return this
// Super Class
class UserCreator {
	constructor(_name, _score) {
		this.name = _name;
		this.score = _score;
	}
	sayName() {
		console.log('I am ' + this.name);
	}
	increment() {
		this.score++;
	}
}

const user1 = new UserCreator('Rohit', 4);
user1.sayName(); // I am Rohit

// Sub Class
class PaidUserCreator extends UserCreator {
	constructor(_paidName, _paidScore, _accountBalance) {
		super(_paidName, _paidScore);
		this.accountBalance = _accountBalance;
	}
	increaseBalance() {
		this.accountBalance++;
	}
}
const paidUser1 = new PaidUserCreator('Anubha', 4, 25);
paidUser1.sayName(); // I am Anubha
paidUser1.increaseBalance();
⚠️ **GitHub.com Fallback** ⚠️