OOP in prototype style in JavaScript
As we know, there are two kinds of inheritance in JavaScript:
– OOP in the functional style;
– OOP in the prototype style;
Prototype style is more popular because it has the main advantage – methods in prototype are automatically available everywhere and always. Why? Methods are written in object, which is linked in a special prototype property. This property has every function – it refers to the object with a single property constructor:
1 2 3 4 | function F() {}; F.prototype = { constructor: F }; |
Objects-prototypes are used in native constructors (Object.prototype, Array.prototype etc) – built-in methods are saved there, for example, toString, join, others.
We can also add our own methods in the object constructor, for example:
1 2 | Object.prototype.countSomething = function() {...} F.prototype.countSomething = function() {...} |
And these methods will be available to the new object, which will be created by constructor F:
1 2 3 4 | function F() {}; F.prototype.countSomething = function() {...}; var f = new F(); f.countSomething(); // will work! |
How?
F.prototype property literally means that when you run function F it will create the new object that will receive f.__ proto__ reference to the object-prototype with all its methods:
It turns out that:
1 2 3 | alert(f.__proro__ == F.prototype) // true; alert(f.countSomething == F.prototype.countSomething); // true alert(f.__proro__. countSomething == F.prototype.countSomething); // true |
Note the last two strings: if the method countSomething() was not found in the object f, created by constructor F, the search continues in its object-prototype (f.__ proro__).
Let’s go ahead and look at the constructors inheritance one from another. Let we have 2 constructors: Second will inherit from First:
1 2 3 4 5 | function First() {...}; First.prototype = {...}; // здесь общие методы в объекте-прототипе function Second() {...}; Second.prototype = {...}; // здесь конкретные методы в объекте-прототипе var obj = new Second(); |
The inheritance algorithm is this: if the desired method is not found in the object obj, we are looking for it in Second.prototype (prototype object constructor, which has created our obj); if the desired method is not there, we will look for it in First.prototype:
obj> Second.prototype> First.prototype
As we already know, when you create a new object obj, it automatically obtains a reference to the object-prototype: obj.__ proto__ == Second.prototype. And how to force the Second.prototype to inherit from >First.prototype?
Of course, you can code such a structure: Second.prototype.__ proto__ = First.prototype, but in fact there is a special technique:
1 | Second.prototype = Object.create(First.prototype); |
It creates a new empty object with reference to the prototype object First.prototype. Next, we can safely add the needed methods to Second.prototype. The final sequence of the inheritance:
1 2 3 4 5 6 | function First() {...}; // объявили общий конструктор First.prototype = {...}; // добавили методы в его объект-прототип function Second() {...}; // объявили конкретный конструктор Second.prototype = Object.create(First.prototype); // создали пустой объект с ссылкой на прототип First.prototype Second.prototype = {...}; // добавили методы в его объект-прототип var obj = new Second(); // запустили конструктор |