I know there are similar questions like this, but I want to see if those answers are still valid given optimizations in new Javascript engines.
In my opinion, the biggest benefit about defining functions inside the constructor is that you can easily avoid having to know the value of 'this' keyword:
var Person = function() {
var self = this;
self.firstName = null;
self.lastName = null;
self.fullName = function() {
return self.firstName + self.lastName;
};
};
This approach is recommended by Knockout Managing 'this'. This is a great advantage, especially when the code is being modified by many developers as it is really simple to understand and use.
The other approach would be to use the object prototype:
var Person = function() {
this.firstName = null;
this.lastName = null;
};
Person.prototype.fullName = function() {
return this.firstName + this.lastName;
};
In this case there are performance advantages because functions objects will be created once. However the main issue I have with it is that it might be complicated to handle the 'this' keyword. The above example is very simple, but if you have event handlers, forEach calls, jQuery each() calls, methods being call from different contexts, etc., it is easy to make a bad use of this.
Of course, if you understand how 'this' works and are aware of how methods are being called, you shouldn't have much issues. However, in my experience, this takes time and it is error prone, especially when code is crafted by many developers.
I know that new JS engines, like V8, are applying optimizations to cases where you declare functions inside the constructor by creating hidden classes: How the V8 engine works?.
So my question is, given these optimizations done by new JS engines and the complexity of having to handle the 'this' keyword, does it still make sense to use the prototype based approach? What I would loose by using the approach of putting everything inside the constructor?
UPDATE 1:
I just did a micro-benchmark on Chrome (version 42). I create 1M objects with functions inside constructor and functions in prototype. It is a very simple object with two variables and three functions and the results are like this:
Functions inside constructor: 1.91 seconds
Functions in prototype: 1.10 seconds
Sounds like even with those optimizations in V8 it is still 73% faster. However this was a micro-benchmark. Not sure if that will be a big difference in real world applications.
UPDATE 2:
I also took a look at memory consumption and there are big differences as well. For functions inside constructors:
Shallow size: 64,000,120
Retained size: 336,001,128
For prototype functions:
Shallow size: 40,000,000
Retained size: 40,000,000
Either optimizations with hidden class are not that good or I'm missing something about that. I'm using monomorphic code (constructors with no args) as suggested by V8, but not sure if I'm doing something wrong.
UPDATE 3:
Here is the link of the test I did in case someone can point out something wrong in there: http://jsperf.com/dg-constructor-vs-prototype
When you define a function inside the constructor as this. myFunction=... , it is specific to your instance. This means that it must be constructed and kept in memory for all instances, which may be heavy. It also can't be inherited .
Let's note once again – technically, any function (except arrow functions, as they don't have this ) can be used as a constructor. It can be run with new , and it will execute the algorithm above. The “capital letter first” is a common agreement, to make it clear that a function is to be run with new .
So what's the difference between constructor and prototype? A short answer is that the constructor is a function that is used to create an object, while the prototype is an object that contains properties and methods that are inherited by objects created from a constructor.
constructor. The constructor property returns a reference to the Object constructor function that created the instance object. Note that the value of this property is a reference to the function itself, not a string containing the function's name.
Like @Ersin Basaran mentioned, a function created inside the constructor is unique for every object instance, unlike when it is created using the prototype makes it the same function for every object instance.
However, after introducing classes in ES6 (ECMAScript2015), if you use a class to create a method instead of using a constructor function, and you create this method outside the constructor (but inside the class), it will be the same for every object instance, just like when using the prototype.
Here is an example of creating a fullName()
method:
class Person {
constructor () {
var self = this;
self.firstName = null;
self.lastName = null;
}
fullName () {
return self.firstName + self.lastName;
}
}
Person.prototype.fullName2 = function () {
return this.firstName + this.lastName;
};
var a = new Person();
var b = new Person();
console.log(a.fullName == b.fullName); // returns true
console.log(a.fullName2 == b.fullName2); // returns true
I hope this helps.
I perform a quick test. If you declare function in the constructor, two object instances have different function instances even after optimizations. However with prototype, you have only one instance of the function which explains the performance difference.
var Person = function () {
var self = this;
self.firstName = null;
self.lastName = null;
self.fullName = function () {
return self.firstName + self.lastName;
};
};
Person.prototype.fullName2 = function () {
return this.firstName + this.lastName;
};
var a = new Person();
var b = new Person();
console.log(a.fullName == b.fullName); // returns false
console.log(a.fullName2 == b.fullName2); // returns true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With