Advantages of Using Prototype, VS Defining Methods Straight in the Constructor

Advantages of using prototype, vs defining methods straight in the constructor?

Methods that inherit via the prototype chain can be changed universally for all instances, for example:

function Class () {}
Class.prototype.calc = function (a, b) {
return a + b;
}

// Create 2 instances:
var ins1 = new Class(),
ins2 = new Class();

// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2

// Change the prototype method
Class.prototype.calc = function () {
var args = Array.prototype.slice.apply(arguments),
res = 0, c;

while (c = args.shift())
res += c;

return res;
}

// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3

Notice how changing the method applied to both instances? This is because ins1 and ins2 share the same calc() function. In order to do this with public methods created during construction, you'd have to assign the new method to each instance that has been created, which is an awkward task. This is because ins1 and ins2 would have their own, individually created calc() functions.

Another side effect of creating methods inside the constructor is poorer performance. Each method has to be created every time the constructor function runs. Methods on the prototype chain are created once and then "inherited" by each instance. On the flip side of the coin, public methods have access to "private" variables, which isn't possible with inherited methods.

As for your function Class() {} vs var Class = function () {} question, the former is "hoisted" to the top of the current scope before execution. For the latter, the variable declaration is hoisted, but not the assignment. For example:

// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); }

// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }

difference between using this and prototype to define methods of a class in JavaScript?

In most situations you will have the same functional result. But internally it's quite different in that when you attach the functions to this, then every instance of the type gets its own copy of the function. By attaching the functions to prototype, all instances share the same function instances. Using prototype reduces memory usage.

Why do we add methods using the prototype property of the constructor function?

In your second example you recreate the logName function every time you create a new instance of MyExample. If you use the MyExample's prototype then one logName method is shared across all instances of the MyExample object and context is passed around automatically.

The prototype also allows you to add a new method at a later point that can be accessed by already-existing objects of that type or globally modify a method for all objects of a type.

This question touches on the same topic if you would like more information, Advantages of using prototype, vs defining methods straight in the constructor?

Attach method to prototype or constructor function - they both work fine, why is either better?

By attaching a method to a prototype, each instance of the object doesn't have to store the exact same method, thus reducing the memory footprint.

Since methods (behaviors) don't often vary from instance to instance, individual instances don't need to store the same behavior. By putting it on the prototype, all instances will just inherit it.

And, when setting the method on the prototype, do so outside of the constructor function, otherwise each instance will just re-create the same method on the one prototype, causing the last method to be overwritten by the exact same new method.

"use strict";

function Aircraft(a, b, c) {
this.manufacturer = a;
this.numberOfEngines = b;
this.costPerEngine = c;
}

// Prototype modifications should happen outside of the
// constructor function so that they are processed just
// once and not every time the constructor is invoked.
Aircraft.prototype.totalCost = function() {
return this.numberOfEngines * this.costPerEngine;
}

// At this point, the prototype is all set, so calling the
// constructor (which inherits from the prototype) creates
// a new object instance that has inherited the method.
let thunderbolt = new Aircraft('Republic', 1, 20000);

console.log(thunderbolt.totalCost());

What's the difference between this.function and prototype.function?

Functions on the prototype are only created once and shared between each instance. Functions created in the constructor are created as new objects for each new object created with the constructor.

As a general rule functions should be on the prototype since they will generally not be modified for different objects of the same type, and this has a slight memory/performance benefit. Other properties like objects and arrays should be defined in the constructor, unless you want to create a shared, static property, in which case you should use the prototype.

Its easier to see the distinctions with normal objects or arrays rather than functions

function Foo(){
this.bar = [];
}
var fooObj1 = new Foo();
var fooObj2 = new Foo();

fooObj1.bar.push("x");
alert(fooObj2.bar) //[]

as opposed to:

function Foo(){
}

Foo.prototype.bar = []
var fooObj1 = new Foo();
var fooObj2 = new Foo();

fooObj1.bar.push("x");
alert(fooObj2.bar) //["x"]

Difference between method in a constuctor function vs function's prototype property

Here's a post I recently did about that and here's a demo. In the demo, take a look at Test2 and where foo and bar are located in the chain.

var Test2 = function() {              //foo attached via constructor
this.foo = 'foo'; // each instance has "it's own" foo
}
Test2.prototype.bar = function() {}; //bar attached via prototype
// all instances "share" the same bar
var mytest2 = new Test2();

(3) <-------- (2) <--------- (1) <- prototype chain
Object -> Test2 prototype -> mytest2
'--> bar '--> bar (from prototype)
'--> foo (from constructor)

Basically, anything attached via constructor appears at every instance, but "belongs to that instance". Modifying that property from an instance only modifies it at the current instance.

On the other hand, the ones attached via the prototype is appears on all instances of that object and are "shared". Modifying that property changes this property for all instances.

Why would I use prototype when I can just attach a function to the constructor?

Actually yes, there is a difference. When you adding a method or property via prototype you can be sure that this method/property will be created only once and they will be contained in the prototype object. However, if you just add your methods to a function that methods will be cloned with each new instance of your class. Lets say you have 10 object instances from your class. If you use prototype you will have only 1 method for all this 10 instances. And if you added method to a function object itself you will have 10 methods copy.

Effect of using .prototype to declare a method?

this.area = function(){} creates a new function and assigns it to the area property of this. Circle.prototype.area = function(){} creates a function once, and assigns it to the prototype of objects created by the Circle() constructor.

Why use prototype for methods instead of this.methodName

Well, you should use prototypes because of code reuse and inheritance.

Basically, if you bind a method to the this keyword, you are providing that method to only that particular instance, while with prototype, you write the method for all instances of that class.

ex:

function Person(name) {
this.name = name;
this.toString = function() {
return this.name;
}
}
var bob = new Person('Bob');
var jim = new Person('Jim');
jim.toString = function() {
return "I have amnesia, I forgot my name!";
};

Now, although bob and jim are both persons (instances of the same class), they behave differently, because they have their own set of rules (methods) that they rely on.

If you were to use a prototype:

function Person(name) {
this.setName(name);
}
Person.prototype = {
name : 'default name',
setName : function(name) {
this.name = name;
},
toString : function() {
return this.name;
}
};
var bob = new Person('Bob');
var jim = new Person('Jim');
Person.prototype.toString = function() {
return "I have amnesia, I forgot my name!";
};

Now, all of your persons behave the same.

Using prototypal inheritance is benefic for code reuse and it won't load the memory with unnecessary duplicate things. + Updating classes is muuuch more easy this way.



Related Topics



Leave a reply



Submit