Functions inside constructor vs prototype

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


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
链接地址: http://www.djcxy.com/p/26718.html

上一篇: Pywin32将.docx保存为pdf

下一篇: 构造函数内部的函数vs原型