Prototype

Prototype is an object from which other objects inherit properties and the way we can inherent property to the object. You can not define Class in JavaScript. However, we can do a similar thing. How we can create class-ish something and inherent. The answer is Object. Any object has an internal connection between other objects internally, which is called Prototype. Prototype object has own prototype and search property through Prototype. This is called prototype chain. If prototype chain ends, it returns null.

The syntax someObject.[[Prototype]] referes prototype of someObject which is equal to someObject.__proto__

img

Here is prototype chain

Cat.__proto__ === Function.prototype
Cat.prototype.__proto__ === Object.prototype

Object.__proto__  === Function.prototype
Function.__proto__  === Function.prototype
Function.prototype.__proto__ === Object.prototype

Object.prototype.__proto__ // null => this is end of prototype chain

myCat.__proto__ === Cat.prototype // true
myCat.__proto__.__proto__ === Object.prototype // true
Cat.prototype.__proto__ === Object.prototype // true

How prototypal inheritance works

Here is parent object.

var animal = {
  bark: function(bark){  
    return bark;
  },
  stop: function(){
    return this.bark("Baw");
  }
};

It is kind of obsolete technic to make an inherent relationship.

var dog = {};
// Set the object prototype
dog.__proto__ = animal;

console.log(dog.__proto__ === animal); // true
console.log(dog.bark("wao")) //wao
console.log(dog.stop()) //"Baw"

since ES5, it is better syntax.

var dog = Object.create(Animal);

console.log(dog.__proto__ === animal); // true
console.log(dog.bark("wao")) //wao
console.log(dog.stop()) //"Baw"

Object.create create empty object and add __proto__ on it.

javascript-inheritance-patterns


Prototype Inheritance gives reference to child

Variable assignment is done by passing value. When you refer the property of an object, it is not passed by value which means not copy of the value. It refers to parent property through prototype chain if it can not find property in itself. Deep prototype chain can make program slower so that we have to make sure you don't create too deep to refer unnecessarily.

Ex1:) Pass by Reference

var animal = {
  name: "kei"
}

var dog = {}

dog.__proto__ = animal

dog.name // "kei"

animal.name = "John"

dog.name // "John"

Ex2:) Pass by Reference

var e = {
  message: "Hello"
}


var f = Object.create(e);
console.log(f.__proto__);
console.log(f.message); // "Hello"

e.message = "Error"
console.log(f.__proto__);
console.log(f.message); // Error

Ex3:) Pass by Value

var a = [1,2,3];
var b = a; // Copied value

console.log(a); //[1,2,3]
console.log(b); //[1,2,3]

a = [4, 5, 6];
console.log(a); //[4,5,6]
console.log(b); //[1,2,3]

Ex4:) Pass by value

var c = {
  a: [7,8,9]
}

var d = c.a //copied value [7,8,9]

c.a = [10, 11, 12];

console.log(c.a); //[10, 11, 12]
console.log(d); //[7, 8, 9]

Create inheritance

Creating inheritance consists of 2 steps. Create empty object that has a linkage to parent's prototype and call parent function with child this context.

function Dog(name) {
  Animal.call(this, name);
}

function Animal(name) {
  this.name = name;
}

Dog.prototype = Object.create(Animal.prototype);

var dog = new Dog("kei");

// Dog {name: "kei"}

The code is equivalent to...

class Animal {
  constructor(name) {
    this.name = name;
  }
}

class Dog extends Animal {
  constructor(name) {
   super(name);
  }
}

__proto__ and prototype in JavaScript

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new

When creating a function, a property object called prototype is being created automatically and is being attached to the function object. This new prototype object also points to or has an internal-private link to, the native JavaScript Object. If you will create a new object out of Foo using the new keyword, you basically creating (among other things) a new object that has an internal or private link to the function's prototype Foo we discussed earlier

this in prototype

function Animal(name){
  this.animalName = name;
}

function Plant(name){
  var plantName = name;
}

var animal = new Animal("Kei");
var plant = new Plant("John");

img
img

When we don't bind variable on this context for Plant, it will be not accessed from an object.
We attached animalName by using this keyword.

What happened in this case?

function Animal(name){
  this.animalName = name;
  this.printName = function(){
    console.log(this.animalName);
  }
}

function Plant(name){
  var plantName = name;
  this.printName = function(){
    console.log(plantName);
  }
}

var animal = new Animal("Kei");
var plant = new Plant("John");

console.log(animal.printName());
console.log(plant.printName());

img
img

Closure works on Plant constructor function. animal.printName() access own property animalName. Plant does not have property plantName but access value from closure.

function plant(name){
  var plantName = name;
  this.printName = function(){
    console.log(plantName);
  }
}

plant("John");

What if we call this plant function as not a constructor but function.
Unless object created from a constructor, this context is global scope in this case so that this context will be the window.

function Dog(){};

Dog.prototype = {
  legs: function(){
  },
  height: function(){
    return this.height;
  }
};

var dog = new Dog();

dog.__proto__
// Object {
//   legs: function(){
//   },
//   height: function(){
//     return this.height;
//   }
// }

dog.__proto__ == Animal.prototype // true

dog refers to Dog prototype. The __proto__ getter function exposes the value of the internal [[Prototype]] of an object.

var o = {}

Object.prototype === o.__proto__ //true

o.constructor === Object;

var f = function(){}
Function.prototype === f.__proto__
var Cat = function(name){ this.name = name; }
var myCat = new Cat("Kei");

myCat.prototype
myCat.__proto__ // {}

Cat.prototype = { getName: function(){ return this.name }}

myCat.__proto__

How instance refers to prototype? It is not whole copy of constructor function. Prototype object of constructor is always referred from instance object dynamically through prototype chain.

function Cat(){}

var myCat = Cat("Kei");
myCat.__proto__

// Object >
//   constructor: Cat(name)
//   __proto__: Object

Cat.prototype.getName = function(){
  return this.name;
}

myCat.__proto__
//  constructor: Cat(name)
//  getName: function()
//  __proto__: Object

Constructor property on instance points prototype.constructor

Instance objects does not have constructor property. Prototype of constructor function has constructor. You might have called constructor property on the instance.

function Cat(){}
var cat = new Cat();
Object.prototype.hasOwnProperty.call(cat, "constructor"); // false
Object.prototype.hasOwnProperty.call(cat.__proto__, "constructor"); // true

Why you might want to use prototype method of Built-in Object?

Object.prototype.hasOwnProperty.call()
Array.prototype.slice.call(arguments)

{}.hasOwnProperty
[].slice

{}.hasOwnProperty and [].slice call method through prototype chain which takes more time.

ES6 class

ES6 provide class syntax. However, it is just syntax sugar and still Prototype.

super

super keyword allows to go up prototype chain and access to upper object.

class Animal() {
  constructor(name) {
    this.name = name;
  }
}

class Dog() extends Animal {
  constructor(name) {
    super(name)
  }
}

results matching ""

    No results matching ""