I’m writing this post on javascript prototypes to help me further understand what they are by documenting, or rather summarizing, what I read. I hope that by doing this I also help you understand the subject. Prototypes, the prototype chain, the new keyword, the ES6 class keyword, Object.assign will all be discussed.
What are javascript prototypes?
A javascript prototype is like a special attribute which every object has. It's a pointer to another object. It's javascript's way of handling inheritance.// create a human object function human() {}; // Create a function speak in the human object's prototype human.prototype.speak = function(msg) { console.log(msg); } // Now create an object Joe that has the same prototype as the human object let Joe = Object.create(human.prototype); Joe.speak('hi!'); // hiIn the example above, I create a human object simply by making it a function. In javascript, functions are objects as well. Then, I create a speak function in that object's prototype. This function just logs whatever message you pass it to. After that I create a Joe object, which you can imagine is like an instance or implementation of the human object. I use Object.create which is a new way to create objects since ES5. It creates a new object with the prototype you pass it, in this case, the human object's prototype. So when I write Joe.speak in the end, the javascript engine will first look for the function speak in the Joe object, and it wont find it, so it will go up the prototype chain and look for it in the human object, and it will find it there.
Prototypal vs Classical inheritance
If you're familiar with languages like C++ or Java (amongst others) then you know about classical inheritance. Javascript does not have classical inheritance like Java or C++ does. As said before, javascript uses prototypes to handle inheritance, this is called prototypal inheritance. In classical inheritance, you make a blue print and then you instantiate that. You generally can't use the blue print. In prototypal inheritance, you don't have blue prints, objects just inherit from other objects via the prototype. Prototypal inheritance has its advantages over classical: It's simpler. There's no classes, no interfaces and other things classical inheritance brings, just objects. It's more powerful. you can do everything classical inheritance does, and more. You can for example hand pick which properties to inherit or not inherit any properties at all, just the prototype, with Object.create.What about the 'class' keyword in ES6?
ECMAScript 6 (ES6) or javascript2015 brought in a lot of things to the language. One of it is the class keyword and with it, brought a new syntactical way to create objects:class human { say(msg) { console.log(msg); } } let joe = Object.create(human.prototype); joe.say('still prototype based')It's kind of deceiving, because this new syntax resembles classical inheritance a lot. So let's be clear here: this is just syntactical sugar. Javascript is still prototype based.
JavaScript classes are introduced in ECMAScript 6 and are syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance. source
Are you saying I shouldn't use the 'class' keyword?
Actually, People have spoken out against the use of the class keyword.The bottom line: Class doesn’t give you any power that isn’t already supplied by factory functions and the prototypal OO built into the language. All you’re doing when you create a class is opting into a less powerful, less flexible mechanism and a whole lot of pitfalls and pain.Read the linked post if you want to know more about why not to use class. The author, Eric, has a lot of experience in this and explains it well.
Object.create vs the 'new' keyword
Maybe you have noticed that I'm not instantiating objects with the new keyword in my examples, but rather using the Object.assign function. There's a reason for this. When you inherit from an object using the new keyword, you also inherit all properties of that object. In other words, you are executing the constructor function of the parent object. With Object.create you do not run the constructor function of the parent object, so you only inherit the prototype.let Joe = function(age, sex) { this.age = age; this.sex = sex; this.secret = "I eat cookies at midnight"; } let babyJoe = new Joe(2, "male"); console.log(babyJoe.secret); //I eat cookies at midnightMost of the time, you only want to inherit the prototype to set up the prototype chain. Check the example above, why should babyJoe know Joe's secret? You don't have this problem with Object.create as you only inherit the prototype:
let Joe = function(age, sex) { this.age = age; this.sex = sex; this.secret = "I eat cookies at midnight"; } let babyJoe = Object.create(Joe.prototype); console.log(babyJoe.secret); //undefinedSo it's preferable to use Object.create.
Leave a Reply