Object Prototype
A Prototype is an object that can be inherited by another object. Javascript is an example of Prototype-based programming [1] where behaviors are reused using prototypes.
Every object in javascript has a default prototype Object.prototype
which can be looked up using property __proto__
or simply using Object.getPrototypeOf
method.
const obj = {
age: 1
}
console.log(Object.getPrototypeOf(obj))
// {__defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, __lookupSetter__: ƒ, …}
Prototype chain
An object has prototype where prototype is an object. This prototype object can again have another prototype object, until it results into null
which usually happens when Object.prototype
reaches.
obj.__proto__ // returns Object.prototype
obj.__proto__.__proto__ // returns null as Object.prototype.__proto__ is null
Prototype chain is used for method lookup on objects. If a method does not exist on the object, javascript looks for method in its prototype. If not found in prototype, it goes deeper into prototype chain.
obj.toString() // calls Object.prototype.toString
In the above example, toString
method does not exist on the obj
directly. It gets found in obj
’s prototype.
Set prototype of an object
Prototype of an object can be set using Object.create
method which takes a prototype object.
const objProto = {
getValue() {
return this.value
}
}
const obj = Object.create(objProto)
obj["value"] = 1
obj.getValue()
// 1
Class or function prototype
When we define a class, all the methods go to class’s prototype object. This allows javascript to reuse same methods for class instances.
We can find access prototype using prototype
property on class.
class A {
constructor() {
this.value = 1
}
getValue() {
return this.value
}
}
a = A()
a.__proto__ === A.prototype
When the class is initialized using new
, instance’s __proto__
gets class’s prototype
object.
The same thing happens with function. When a function is called using new
, prototype
objects assigned to the instance’s __proto__
.
const personProto = {
getName () {
return this.name
}
}
function Person() {
this.name = "john"
}
Object.assign(Person.prototype, personProto)
p = new Person()
p.getName()
// john