tl;dr: Understanding Prototypal inheritance, uses & specifics. Composed with code, console & explanatory approach. This article is for you: if you know how inheritance works, basic OOP's concept in JS and two other methods of inheritance, i.e. via ES5 Constructor functions and via ES6 classes functionality.
...
Javascript is a prototype based language as it enables inheriting the prototypes of an object. A native JS Object in JS have it's own inbuilt bag of properties, and these bag of properties can be inherited by another Object via prototype. For example:
console.log(Array.prototype); //brings all basic properties and methods associated with an Array Object and appends it to Array.prototype.
Definitions of terms related to Prototypal Inheritance:
- Prototypal inheritance means objects and their associated methods and properties can be shared, extended, and copied from one Object to another Object.
- A prototype is basically another object that can be used as a fallback source of properties.
- Prototypal Chain is a lookup mechanism for properties on an object. If an Object's property is accessed, JavaScript initially search on the Object itself. If the property isn't found, it will climb up all the way to proto-chain until it is found ( or ends up at null if not found :/).
Some Codewalks for practical learning:
1. Creating a Constructor function using ES5 functionality and check if it's prototype exist?
Whenever you create a constructor function, a property object called prototype is created automatically and gets attached to the function Object(i.e. our constructor function that has a state
).
Note: This new prototype object also points to, or has an internal-private link to, the native JavaScript Object.
The following example creates a Constructor function, Mike:
function Mike () {
this.name = 'Mike';
this.skill = 'JavaScript';
}
//Mike inherits an Object prototype. The "prototype" gets created with Constructor function Mike, declaration automatically.
Mike.hasOwnProperty('prototype');
console.log(Mike.prototype);
The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it)~ MDN
2. Adding properties to a function prototype.
The following syntax defines how to assign properties and methods to a functional prototype consecutively:
Syntax: function_name.prototype.property_name = property_value;
Syntax: function_name.prototype.method_name = function () { return ... }
Mike.prototype.putName = function () {
return 'My name is ' + this.name;
}
console.log(Mike.prototype); //putName method added to Mike prototype
Here, putName method gets created as a prototypal method.
3. Inheriting Properties from Parent to Child.
Add a "new" keyword to make an instance of the parent Object for inheriting properties.
For example:
var Joe = new Mike();
console.log(Joe); //Son(joe) inherits father prototypal properties
Behind the scenes, when you call: var Joe = new Mike();
JavaScript actually perform below operation:
var Joe = new Object();
Joe.[[Prototype]] = Mike.prototype;
Mike.call(Joe);
4. How do browser find which properties belong to which object?
The browser initially check child Object properties [i.e. own-instance properties] if not found, consequently it searches inherited prototypal properties, if not found, then it traverses proto of the Object to inherit to one level, if not found again, then it traverses proto of the proto till the end of the chain level.
But what's proto ?
_ proto _ is an internal property that ties Object to its prototype.
In layman terms, proto acts as a wormhole that references properties from one Object to another Object, during prototypal chain lookup mechanism.
For example:
Conside the Prototypal chain built using above code:
// Joe ---> Mike ---> Object.prototype ---> null
5. Why do we need Prototypal Inheritance(PI)?
PI helps in applying DRY principle to Object instances as it helps in transferring a pool of properties from Parent object to child Object implicitly. We don't need to create properties in every Object instances.
...
Some know-hows while dealing with Prototypal Inheritance:
Object.proptotype is supported by various browsers and is very fast. It's also Just-in-time(JIT) Compilation optimizable in nature.
Prototypal Inheritance enables all the properties you define in the parent prototype to be effectively shared by all instances. Changes in the Parent instance properties will be mitigated automatically to all Child Instances.
Null has no prototype, thus ends the prototypal chain. [ P.S: typeof Null= object]
A function in JavaScript always have a default "prototype" property — with one exception: an Arrow function. Arrow function doesn't have a default prototype property.
Making prototypal Code performant. If code is performance constrained, look up time for properties in prototypal chain can have negative effects. As deeper you go in the scope chain, the more computational overheads occurs as [[Prototype]] is looked recursively. To solve the lookup problem, an inbuilt property called as hasOwnProperty can be used. It deals with an Object's own properties, returns a boolean after search and does not traverses whole prototypal chain. As a developer, be aware of the length of your prototypal chains and break them up if necessary to avoid possible performance problems.
Don't extend Object.prototype for adding non-native properties. It breaks encapsulation, and creates a "Monkey Patching" pattern.
Initializations of constructors on parent object might put overload of unwanted methods in child. Be careful while doing it.
Read more about the topic from below resources:
- proto vs prototype
- Talk on Understanding Prototypal Inheritance pattern
- When Not to extend Prototypal chain
- Prototype.js
- MDN - prototypal inheritance
References: MDN, Stack-overflow, V8 -Blog and Internet Blogs.
Prototypal Inheritance was my first </> Article on dev. Any changes or constructive feedback is highly welcome:) Thanks for Reading.❤️
Top comments (2)
Well explained brother. 🔥
Thanks Rajat. ❤️️