Contents

Prototype Inheritance in Javascript

What is prototype chain and why exist?

Prototype Chain is the built-in mechanism that allows objects to inherit features (properties and methods) from other objects.

Main initial reason is to save the memory space. The inherent idea from OOP langrage(java specifically on those days) is very efficient and obvious way. Prototype chain is a lightweight and flexible method to achieve.

For Instance, If every single object or array you created had to store its own copies of all methods (like toString, valueOf, or array methods), it would consume a massive amount of memory.

Prototype

prototype

Foo.prototype.constructor === Foo; // true
f1.__proto__ === Foo.prototype; // true
f1.constructor === Foo; // true

f1 don’t have constructor, however depends on prototype chain engine will search f1.__proto__. This is line is equivalent to Foo.prototype.constructor === Foo

f1 instantiate a Foo:

  1. f1.__proto__link Foo.prototype
  2. f1 have a constructor which is Foo since Foo.prototype have a constructor

Object.create()

Syntax is Object.create(proto[, propertiesObject])

var newObj = Object.create(obj);
newObj.__proto__ == obj; // true

new

When js running this line:

let person1 = new Person(...);

new actually doing:

  1. Creates a blank, plain JavaScript object person1 = {};
  2. Links (sets the constructor of) this object to another object; person1.constructor is Person
  3. Passes the newly created object from Step 1 as the this context; this -> person1
  4. Returns this if the function doesn’t return an object.

Prototype Chain

This is object example. But Object is NOT we used here

Person = {
  name: 'text',
  age: 12,
};

const p1 = {};
p1.__proto__ = Person; // it is wrong

1

function Person(name, age) {
  this.name = name;
  this.age = age;
}

console.log(Person.prototype); // {} (empty obj)
console.log(Person.prototype.constructor === Person); // true

2

Just for understanding. This is NOT right way

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const p1 = Object.create(Person);
console.log(p1.__proto__ === Person); // true

new instance should use function Prototype as chain

This is the right way

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const p1 = Object.create(Person.prototype); // build chain
console.log(p1.__proto__ === Person.prototype); // true

also you could link manually

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const p1 = {};
p1.__proto__ = Person.prototype; // link chain manually

p1.constructor('p1', 30);

console.log(p1.age);

How to initialized

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const p1 = Object.create(Person.prototype);
Person.apply(p1, ['p1', 31]);

const p2 = Object.create(Person.prototype);
p2.constructor('p2', 32);
console.log(p1); // Person { name: 'p1', age: 31 }
console.log(p2); // Person { name: 'p2', age: 32 }

If you want a instance function

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.print = function () {
  console.log(this.name, this.age);
};

const p1 = Object.create(Person.prototype);
const p2 = Object.create(Person.prototype);
p1.constructor('p1', 31);
p2.constructor('p2', 32);

p1.print();
p2.print();

Summary

const myNew = (constructor, ...args) => {
  const newObj = Object.create(constructor.prototype);
  const result = constructor.call(newObj, 'p1', 31);

  return typeof result === 'object' ? result : newObj;
};
const p1 = (Person, 'p1', 31);
// equivalent to
const p1 = new Person('p1', 31);

Person.prototype can be consider as a share level.

ES5 inheritance

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function () {
  alert(this.name);
};
function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;
}
SubType.prototype = Object.create(SuperType.prototype, {
  constructor: {
    value: SubType,
    enumerable: false,
    writable: true,
    configurable: true,
  },
});
SubType.prototype.sayAge = function () {
  alert(this.age);
};
let instance = new SubType('gim', '17');
instance.sayName(); // 'gim'
instance.sayAge(); // '17'

es5

ES6 inheritance

class SuperType {
  constructor(name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
  }
  sayName() {
    alert(this.name);
  }
}
class SubType extends SuperType {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
  sayAge() {
    alert(this.age);
  }
}
let instance = new SubType('gim', '17');
instance.sayName(); // 'gim'
instance.sayAge(); // '17'

es6