Differences between connecting a function to a prototype or not

What's the difference between:

function Gandalf() { this.color = 'grey'; } Gandalf.prototype.comeBack = function() { this.color = 'white'; } 

and

 function Gandalf() { this.color = 'grey'; this.comeBack = function() { this.color = 'white'; return this; }; } 

And under what circumstances should I bind a method to a prototype, or not?

+4
source share
3 answers

Well, Agent Kay, I approach this question differently than Esailia. Let them start with simple objects. For example, you already have an object named gandalf :

 var gandalf = { color: "grey", comeBack: function () { this.color = "white"; return this; } }; 

There are no constructors in this code. Therefore, this code is easy to understand. Am I right or am I right?


OK, now I'm going to do something amazing. I will create radagast from gandalf :

 var radagast = Object.create(gandalf); radagast.color = "brown"; 

What's going on here? Let me break it down:

  • We create a new object named radagast from gandalf using Object.create . Therefore, radagast inherited from gandalf .
  • We set the color of radagast to brown instead of gray.

To make this even easier, imagine that you and I had the following conversation:

I: Hey Agent Kay, I met Radagast yesterday.

U: Who Radagast?

I: Hmm... do you know who Gandalf?

U: Yes, I do.

I: Well Radagast is just like Gandalf except that he brown instead of white.

This is how inheritance works in JavaScript. You see that JavaScript has prototype inheritance. In prototypical inheritance, objects are inherited from other objects. In this case, radagast inherited from gandalf .


Now their prototype inheritance path is usually implemented in JavaScript, this is strange. I call this the prototype inheritance constructor template . For example, take the code:

 function Gandalf() { this.color = "grey"; } Gandalf.prototype.comeBack = function() { this.color = "white"; return this; }; 

Now that you are creating a gandalf instance, on which object does the instance inherit? It inherits from Gandalf.prototype :

 var gandalf = new Gandalf; alert(Object.getPrototypeOf(gandalf) === Gandalf.prototype); // true 

What happens when you say new Gandalf :

 var gandalf = Object.create(Gandalf.prototype); Gandalf.call(gandalf); 

If you deploy Gandalf.call(gandalf) , you will get:

 var gandalf = Object.create(Gandalf.prototype); gandalf.color = "grey"; 

Now take the second example:

 function Gandalf() { this.color = "grey"; this.comeBack = function() { this.color = "white"; return this; }; } 

In this case, when you create the gandalf instance, you basically do this:

 var gandalf = Object.create(Gandalf.prototype); gandalf.color = "grey"; gandalf.comeBack = function () { this.color = "white"; return this; }; 

Therefore, every time you create a new gandalf , you create a new comeBack function. Thus, if you call new Gandalf 10 times, you will have 10 different comeBack functions.

Compared to this, in the first example, since comeBack defined in Gandalf.prototype , each time we call new Gandalf , we get a new object that inherits from Gandalf.prototype . Therefore, there is only one comeBack function that is shared between all gandalf instances. Isn't that better?


Essentially think of your first example:

 var gandalfPrototype = { create: function () { var gandalf = Object.create(this); gandalf.color = "grey"; return gandalf; }, comeBack: function () { this.color = "white"; return this; } }; var gandalf = gandalfPrototype.create(); // there only one comeBack function 

Similarly, your second example is equivalent to this:

 var gandalfPrototype = { create: function () { var gandalf = Object.create(this); gandalf.color = "grey"; gandalf.comeBack = function () { this.color = "white"; return this; }; return gandalf; } }; var gandalf = gandalfPrototype.create(); // there 1 comeBack for each instance 

Remember that when using new before the function call, you inherit the function prototype function. Not the function itself.


Finally, I would like to say (because I'm a big fan of JRR Tolkien) that this way I will write your code:

 var wizard = { create: function (color) { var wizard = Object.create(this); wizard.color = color; return wizard; } }; var gandalf = wizard.create("grey"); gandalf.comeBack = function () { this.color = "white"; return this; }; var saruman = wizard.create("white"); var radagast = wizard.create("brown"); 

Thanks for reading my answer.

+4
source

The reason to put it on a prototype is that each created object can use the same functional object (functions are just called objects), they only need different identifiers and data. But in the second case, you create unique function objects for each object, even if they can use the same functional object.

Since you seem to know PHP, the difference will be similar to PHP:

 class Gandalf { public $color = "grey"; public function comeBack() { $this->color = "white"; } } class Gandalf { public $color = "grey"; //Create the method inside constructor everytime public function __construct() { $this->comeBack = function() { $this->color = "white"; return $this; }->bindTo($this, $this); } } 

It's hard to say when to use another, when performance is not a concern. Personally, the obfuscation of the constructor function and the extra level of indentation are enough for me to prefer the prototype.

+3
source

To reply:

Under what circumstances should I bind a method to a prototype, or not?

If you have a function that needs to access the private vars object created using a constructor function, it must be inside the constructor function.

 function Gandalf() { var age = '30000'; //approximate this.alertAge1 = function() { alert( age ); }; } Gandalf.prototype.alertAge2 = function() { // age not visible from here }; 
0
source

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


All Articles