Is there a difference between a constructor function and a prototype object when using inheritance?

Consider the following JavaScript snippets:

function foo() { this.bar = function() { }; } // or... (if we used an empty constructor function) foo.prototype.bar = function() { }; 

What is the difference when I do this:

 function baz() { } baz.prototype = new foo(); 

In both cases, baz ends up having a bar member, but what's the difference? Why should I do this in different places?

+6
source share
4 answers

The difference is that the property is in the prototype chain.

Assuming we have f = new foo(); and b = new baz() . Then we have the following situations:

Defining foo without using a prototype:

 +-----------+ +---------------+ | f | | foo.prototype | | __proto__-+---->| constructor | | bar | | | +-----------+ +---------------+ 

bar is a property of the object itself ( f.howOwnProperty('bar') returns true ).

If you instead assign a property to a prototype, this is:

 +-----------+ +---------------+ | f | | foo.prototype | | __proto__-+---->| constructor | | | | bar | +-----------+ +---------------+ 

f does not have its own bar property, but the shared property with all other foo instances.

Similarly for the second fragment, which is obtained either in

 +-----------+ +---------------+ +---------------+ | b | | foo instance | | foo.prototype | | __proto__-+---->| __proto__ -+---->| constructor | | | | bar | | | +-----------+ +---------------+ +---------------+ 

or

 +-----------+ +---------------+ +---------------+ | b | | foo instance | | foo.prototype | | __proto__-+---->| __proto__ -+---->| constructor | | | | | | bar | +-----------+ +---------------+ +---------------+ 

Why do you want to do this?

It is mainly about structure and not wasting memory. You can add functions to an object in constructor functions:

 function Foo() { this.bar = function() {}; } 

but it also means that each instance of foo has its own function, i.e. f1.bar === f2.bar is false , although both functions do the same.

Using a prototype gives you a clean way to separate properties common to all instances and specific instances.

In the end, it is β€œjust” inheritance, which is one concept in software development (for example, aggregation) and can be used wherever it makes sense. The second fragment basically means that baz is-a foo , so the baz instance, in addition to its own properties, has the same properties as the foo instance (inherited).

+10
source

One big difference is that if you change the properties of the prototype, these changes will apply to all instances, including those that already exist, whereas if you change the property that was created in the constructor, it will only change it to the instance which you change it.

Regarding what some of the other answers said about setting bar in the constructor, as a result, each instance has its own copy of the function: this is true if you have a function expression inside the constructor, as shown in the code in the question, but not true if you assigned a link to the function as follows:

 function myFunction() {} function foo() { this.bar = myFunction; } 

In this case, all instances will have a bar property that refers to the same function, but a single instance can still have a bar property assigned to something else without affecting other instances.

+1
source

To add to existing answers:

Creating a prototype function allows you to inherit its inheritance. if you write

 function foo(){} foo.prototype.bar = function(){return 1}; function baz(){} baz.prototype = new foo(); new baz().bar(); //returns 1 foo.prototype.bar = function(){return 2}; new baz().bar(); //returns 2 

However, including it in the constructor will allow other objects that inherit from it to also have this function, but the function is not inherited.

 function foo(){this.bar = function(){return 1};} function baz(){} baz.prototype = new foo(); new baz().bar(); //returns 1 foo.prototype.bar = function(){return 2}; new baz().bar(); //returns 1 
0
source

I think I'm answering the right question, otherwise let me know.

The difference is that using a prototype results in only one instance.

So, for example, baz.bar in one instance matches baz.bar in another. They will share the values ​​inside the "foo" instance:

 function foo() { var x = 0; this.bar = function() {}; this.getVal = function() { return x; } this.setVal = function(val) { x = val; } } function baz() {} baz.prototype = new foo(); var a = new baz(), b = new baz(); a.setVal("1234") console.log(b.getVal()); // prints '1234' 

http://jsfiddle.net/jonathon/7GtRD/

If a and b were directly called by 'foo', then they will not share the values ​​in foo . However, here it is slightly different from setting this.bar and uses a prototype to create the panel.

Using a prototype will create one instance of bar . So a.bar will be the same as b.bar . If you do it differently, it will be two different functions (the same thing).

-1
source

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


All Articles