📜 ⬆️ ⬇️

JavaScript methods

Someday, every JavaScript programmer will realize that JS is an object-oriented language. And here he faces some dangers arising from a lack of understanding of the fact that JS is not a language of classes (like Pascal or Tse-two-crosses), but of prototypes.
So, much has already been written about the problem of inheritance (which is not in JS). I will try to tell about a less illuminated, but perhaps more important, pitfall: the competent implementation of the methods.
Programmers are trying to declare classes in their usual form, because of which there are memory leaks and other unpleasant things. In fact, you just need to learn how to use prototypes.
This article is intended primarily for beginners JS-programmers.

Below I will use the concept of "class" in the sense in which it is understood in Pascal or Tse-two-crosses; at least in JS there are no such classes, generally speaking, but something is very similar in form and meaning.
From the very beginning, two basic things become known to everyone:
  1. class is described by a constructor function;
  2. methods are properties-functions.

Therefore, programmers begin to write quite naturally:
function Test(){ //     this.x=5; this.y=3; //   this.sum=function(){ return this.x+this.y; } //     alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } 

After that, it seems to be what we wanted: we get the Test class with two properties x (initially 5) and y (initially 3) and the sum method, which calculates the sum of x and y. When constructing, a cell is displayed with an X, a player, and a sum.
But what really happens? When constructing a Test object, the Test function is called each time. And each time it creates a new anonymous function and assigns it to the sum property! As a result , each object creates its own, separate method sum . If we create a hundred Test objects, we get somewhere in the memory a hundred sum functions.
Obviously, this can not be done. And it is important to realize this as soon as possible.
After understanding this fact, novice programmers often do the following: create the sum function separately, and assign it to the property in the constructor:
  function Test(){ //     this.x=5; this.y=3; //   this.sum=Test_sum; //     alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } //   function Test_sum(){ return this.x+this.y; } 

As a result, indeed, the Test_sum function is created only once, and each time a new Test object is constructed, only the sum reference is created.
At the same time, this is an illiterate option. Everything can be done much more beautifully and more correctly using the very basis of JavaScript: prototypes:
  function Test(){ //     this.x=5; this.y=3; //     alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } //   Test.prototype.sum=function(){ return this.x+this.y; } 

We create the sum property not of the Test class, but of its prototype. Therefore, each Test object will have a sum function. Actually, then he and the prototype to describe the things that each object has. Moreover, the usual, non-functional properties would also be logical to drive into the prototype:
  function Test(){ //     alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // , ,     Test.prototype.x=5; Test.prototype.y=3; Test.prototype.sum=function(){ return this.x+this.y; } 

The bad thing here is that the declarations of properties and methods go after their use in the constructor. But this will have to accept ...
More here is the unpleasant repetition of Test.prototype. From some point of view, it would be nice to remember that JS is not Ce-two-cross, and we have a proposal with. On the other hand, many reputable people do not recommend using with at all. Therefore, the following options should not be used .
Literally immediately, an unpleasant surprise awaits us: this code does not work.
  function Test(){ //     alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // , ,     with(Test.prototype){ x=5; y=3; sum=function(){ return this.x+this.y; } } 

Why does not work - in some way a mystery. Anyway, and the word prototype will have to be repeated:
  function Test(){ //     alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // , ,     with(Test){ prototype.x=5; prototype.y=3; prototype.sum=function(){ return this.x+this.y; } } 

The advantage here is in grouping the ads of the entire Test class stuffing into one block - with the exception of the remaining constructor. But even with this you can cope if you remember that a function can be declared in at least three syntaxes:
  with(Test=function(){ //     alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); }){ //     prototype.x=5; prototype.y=3; //   prototype.sum=function(){ return this.x+this.y; } } 

The result is almost the natural record with which we started, except that the word this was replaced by prototype ; Well, and moved to the beginning of "other constructive actions" - as I said, with this, unfortunately, will have to accept.
However, if nothing is needed from the constructor except for creating properties and methods, it turns out that beauty is completely:
  with(Test=new Function){ //     prototype.x=5; prototype.y=3; //   prototype.sum=function(){ return this.x+this.y; } } 

However, let's not forget that the with clause is not recommended. Therefore, in the end we will focus on the third option ads .

')

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


All Articles