📜 ⬆️ ⬇️

Wrappers for creating classes: evil or good?

Time after time I read that convenient libraries for creating classes in Javascript, you see, do not correspond to the ideology of the language and those who use them simply need to learn the language. This is said by the ignorant, who themselves have not really understood the language itself or the libraries that they criticize. And so often they say that I decided to write this topic and just give a link
var Foo = new Class({ Extends: Bar, initialize: function(firstname, lastname) { this.parent(firstname); this.lastname = lastname; }, sayHello: function(){ alert(this.lastname || this.firstname); } }); 


Wrappers in normal libraries are completely consistent with the ideology of Javascript and prototype-oriented programming. They simply provide a convenient interface, an alias for using it. Of course, there are libraries that implement “OOP in Javascript” through some different methods, but now we don’t take these into account, but consider them on the example of Mutuls .

For example, for the construction
 MyClass = function() {/* constructor */}; MyClass.prototype.firstMethod = function() {/**/}; MyClass.prototype.secondMethod = function() {/**/}; MyClass.prototype.thirdMethod = function() {/**/}; 


Introduced alias, which allows not to repeat MyObject.prototype . Do not do without this design, but simply do not repeat it. Inside the library will be all the same
 MyClass = new Class({ initialize : function() {/* constructor */}, firstMethod : function() {/**/}, secondMethod: function() {/**/}, thirdMethod : function() {/**/} }); 

')
The following construct is for inheritance (note that it fully complies with the Javascript ideology and is “caught” by the instanceof )
 MyAnotherClass = function() {/* constructor */}; var Tmp = function() { } Tmp.prototype = MyClass.prototype MyAnotherClass.prototype = new Tmp() MyAnotherClass.prototype.constructor = MyAnotherClass; 

Encapsulated in such a simple entry:
 MyAnotherClass = new Class({ Extends: MyClass }); 


And many, many, many. The bottom line is that it does not violate the ideology of JavaScript. It adapts to it and provides a user-friendly interface, but inside it’s all the same as a professional would. After all, the ideology of prototype-oriented programming is not verbosity and the constant mention of the word “prototype”, but incredible extensibility.

Overloaded constructor



And the ideology is violated by just another, very harmful and very popular approach - the overloaded designer:
 var MyClass = function() { /*   */ this.firstMethod = function() {/**/}; this.secondMethod = function() {/**/}; this.thirdMethod = function() {/**/}; /*  ,       */ }; var MyAnotherClass = function() { //  MyClass.apply(this, arguments); this.elseOneMethod = function() {/**/}; }; var myAC = new MyAnotherClass(); console.log(myAC instanceof MyClass); // false 


Which cannot be inherited so that the instanceof works, in which functions are created every time an object is created, which is why the memory flows like a river and the processor cries. Instead of creating a function in one place and giving it a link, we will create it every time. These functions are not present in the prototype (and in embedded objects such as Array, Number and the rest everything is exactly in the prototype), they cannot be redefined or obtained out of context, they are incorrectly determined using hasOwnProperty and work prohibitively slowly (hundreds of times):
 var MyClass = function() { this.method1 = function(){}; }; MyClass.prototype.method2 = function(){}; var myClass = new MyClass; console.log(myClass.hasOwnProperty('method1')); // true console.log(myClass.hasOwnProperty('method2')); // false var Foo = function() { this.method1 = function(){}; this.method2 = function(){}; this.method3 = function(){}; this.method4 = function(){}; this.method5 = function(){}; this.method6 = function(){}; this.method7 = function(){}; this.method8 = function(){}; this.method9 = function(){}; } var Bar = function() {}; Bar.prototype.method1 = function(){}; Bar.prototype.method2 = function(){}; Bar.prototype.method3 = function(){}; Bar.prototype.method4 = function(){}; Bar.prototype.method5 = function(){}; Bar.prototype.method6 = function(){}; Bar.prototype.method7 = function(){}; Bar.prototype.method8 = function(){}; Bar.prototype.method9 = function(){}; /** * Chrome 8 * Foo: 260 * Bar: 26 * Firefox 3.5 * Foo: 22081 * Bar: 158 */ console.time('Foo'); for (var i = 1000000; i--;) new Foo(); console.timeEnd('Foo'); console.time('Bar'); for (var i = 1000000; i--;) new Bar(); console.timeEnd('Bar'); 

I am silent about what will be in Internet Explorer. Check for yourself. You can leave the computer on for the night =)
Even the fact that it allows you to implement pseudo-private methods and variables does not justify this approach for a second.

Once again, the shortcomings of the overloaded constructor list:
* instanceof does not work in children
* significantly more memory consumption
* works tens or hundreds of times slower
* methods are absent in the prototype
* methods are incorrectly defined through hasOwnProperty

Conclusion


Use the fact that you are comfortable and pleasant to users. If you think that MooTools.Class or any other similar library will make your application more readable and easier support - use it! And do not pay attention to everybody who you know who shout about the ideology of Javascript (and she is undoubtedly beautiful)

UPD: This topic was written as an answer to the aux message :
JS preach prototype OOP, insert class crutches - not gut. Learn the language and its capabilities.

I do not claim that the approach in the frameworks is the only correct one. Just you should not avoid such wrappers as MooTools.Class, if someone told you that it, you see, does not correspond to the ideology of Javascript or something like that. _

Source: https://habr.com/ru/post/111393/


All Articles