"Prototype"

. . . don't take them for granted

What this is about?

A brief introduction on

  • Ambiguous nature of the term prototype
  • What prototype means in Javascript
  • How it is being used in our daily code

What this is not about?

 

  • Different ways of Inheritence in Javascript
  • How Object oriented programming is done in Javascript

What is a Prototype?

Every object in Javascript, has a special property which is linked to an object, which is referred as the 'Prototype' of an object.

function Foo() {}

Foo.prototype.myName = 'Anirudh';

The term prototype has been used in two ways 😪

  • [[Prototype]]
  • .prototype

I was wrong!😓

[[Prototype]]

  • For every object which is being created, Javascript internally creates a property named [[Prototype]], and links an object to it.

  • It is this property which serves as the actual prototype for any object.

  • The property can also be null.

  • We can access the property by __proto__/ Object.getPrototypeOf(obj) .

  • The value of the [[Prototype]] is different for unique type of object in Javascript.

  • The [[Prototype]] object is used to implement inheritance.

.prototype

  • This is a property which, is only created for new function declarations, and for some built-in functions

  • These .prototype object have a constructor property, which initially points back to the declared function.

  • All functions in JS, will have their own .prototype property, whose value may differ with the type of function.

  • Since, they are object, they will have their own [[Prototype]] property.
  • It's purpose is to serve as a [[Prototype]] for a different object, or for objects created using new operator on the function declared.

Examples of [[Prototype]]

Since, every object in Javascript will have a [[Prototype]], this means, whatever data we go on to declare will have a [[Prototype]] object of their own.

var obj = {
    'foo' : 'bar'
};
console.log(obj.__proto__);    // Object {}

var arr = [1, 2, 3];
console.log(arr.__proto__);    // []

But if we look closely, these are pointing to different objects, for different types

Recall : The value of the [[Prototype]] is different for unique type of object in JS.

which means arrays, numbers, strings, booleans, functions, object literal, etc.. all will have their own [[Prototype]], pointing to some object.

var a = 2;
console.log(a.__proto__);        // Number {}

var b = 'foo';    
console.log(b.__proto__);        // String {}

var obj = {
    'foo':'bar'
};
console.log(obj.__proto__);      // Object {}

var arr = [];
console.log(arr.__proto__);      // []

var bool = true;
console.log(bool.__proto__);     // Boolean {}

function Foo(){}
console.log(Foo.__proto__);      // function (){}

But  what are these [[Prototype]] pointing to?

Recall : The purpose of .prototype object, of every function, is to serve as a [[Prototype]] objfor a different object, or for object created using new operator on the function declared.

The [[Prototype]] for the different types of objects, are pointing nothing to but the .prototype of the in built classes maintained in Javascript like (Function, Number, String, etc. . .), which is Function.prototype, Number.prototype, String.prototype, Array.prototype, Boolean.prototype, Object.prototype, etc . . .

Examples of .prototype

Whenever a function is created in Javascript, Javascript will internally add a property named prototype to the function, and this is only added to function declarations.

console.log(Object.prototype);         // Object {}

console.log(Number.prototype);         // Number {}

console.log(Function.prototype);       // function (){}

console.log(Array.prototype);          // []

function Foo(){}    

console.log(Foo.prototype);            // Object {}

So, if we look at the diagram of how the linking has been done till now for the code, it will look like this.

var obj = { a : 1 };

function Foo(){}

The .prototype has one special property, the constructor property, which 'initially' points back to the function in which .prototype property is present.

Object.prototype.constructor will point back to the Object function, Foo.prototype.constructor will point back to the Foo function, and so on.

console.log(Function.prototype.constructor);    // Function

console.log(Foo.prototype.constructor);         // Foo

console.log(Number.prototype.constructor);      // Number

console.log(Array.prototype.constructor);       // Array

console.log(String.prototype.constructor);      // String

With the above change, the diagram changes a little.

Since the .prototype is an object the .prototype, will also have it's [[Prototype]], which may point to a different object.

console.log(Function.prototype.__proto__);    // Object {}

console.log(Foo.prototype.__proto__);         // Object {}

console.log(Number.prototype.__proto__);      // Object {}

console.log(Array.prototype.__proto__);       // Object {}

console.log(String.prototype.__proto__);      // Object {}

console.log(Object.prototype.__proto__);      // null

Except, Object.prototype.__proto__ will give us null, indicating that the [[Prototype]] of Object.prototype does not exist.

With the [[Prototype]] in picture for .prototype object, the diagram again undergoes through another modification.

This method of linking an object to the [[Prototype]] of another object, and then so on.. is referred to as Prototype chaining.

The chain needs to end somewhere, and the end of chain is denoted by the fact that [[Prototype]] of Object.prototype is actually null.

This chain is used to look up properties, when the property is not found in the original object.

So if a new instance is created from 'Foo', what will be the [[Prototype]] of the new object?

var fooInstance = new Foo();

It will be "Foo.prototype", and if we, now look at the diagram.

How it is being used in our daily code.

  • The data which we declare.
  • Objects created using new on functions.
  • Object.create to implement inheritance, and alter the [[Prototype]].

Object.create - accepts an object as first parameter, creates an empty object, links the [[Prototype]] of empty object to the object received.

var obj = {
    'foo' : 'bar'
};

var obj2 = Object.create(obj);

console.log(obj2.foo);    // 'bar'
function Foo() {}

Foo.prototype.myName = 'Anirudh';

function KidFoo(){}

KidFoo.prototype = Object.create(Foo.prototype);

var kidFooInst = new KidFoo();

console.log(kidFooInst.myName);        // 'Anirudh'

console.log(kidFooInst.contructor);    // Foo

.prototype object which was initially created for KidFoo, is discarded because it is now replaced with an empty object, whose [[Prototype]] is Foo.prototype

KidFoo.prototype.construtor = KidFoo;

var kidFooInst = new KidFoo();

console.log(kidFooInst.constructor);    // KidFoo

[[Prototype]] are the foundation for inheritance in Javascript.

Thank you!!

Made with Slides.com