Declaring javascript object method in constructor function vs. in prototype

JavascriptOop

Javascript Problem Overview


In creating javascript objects, I can put a method declaration either in the constructor function or in the prototype. For example, say I want a Dog class that has a Name property and a Bark method. I can put the declaration of the Bark method into the constructor function:

var Dog = function(name) {
    this.Name = name;
    this.Bark = function() {
        alert(this.Name + " bark");
    };
}

or I could put in as a method on the prototype object:

var Dog = function(name) {
    this.Name = name;
}

Dog.prototype.Bark = function() {
    alert(this.Name + " bark");
};

When I instantiate objects of type Dog, both approaches seem to work fine:

var dog = new Dog("Fido");
dog.Bark();  //Both approaches show "Fido bark"

Should I prefer one of these approaches over the other? Are there any advantages to using one over the other? Behind the scenes, do these two approaches end up doing exactly the same thing? Which approach do most people tend to favor?

Thanks for the help.

Javascript Solutions


Solution 1 - Javascript

For the example you give, you should use the prototype approach. In general, it depends. The main advantage of the first approach (initializing methods in the constructor) is that you can take advantage of closures by making use of local variables defined within the constructor in your methods. These variables are not directly accessible outside the constructor function so are effectively "private", meaning your API is cleaner than if these variable were instead defined as properties of the object. Some general rules of thumb:

  • If your methods do not use local variables defined in your constructor (your example doesn't), then use the prototype approach.
  • If you're creating lots of Dogs, use the prototype approach. This way, all "instances" (i.e. objects created by the Dog constructor) will share one set of functions, whereas the constructor way, a new set of functions is created every time the Dog constructor is called, using more memory.
  • If you're creating a small number of Dogs and find that using local, "private" variables in your constructor improves your code, this may be the better approach. Use your judgment and do some benchmarks if performance or memory consumption are major concerns.

It is possible to use a hybrid approach whereby only methods that need access to local private constructor variables are defined in the constructor while other methods are assigned to the prototype.

For example, the code below uses a local variable in the constructor to keep track of the number of times this dog has barked while keeping the actual number private, so the barking-related methods are defined inside the constructor. Tail wagging does not require access to the number of barks, therefore that method can be defined on the prototype.

var Dog = function(name) { this.name = name;

    var barkCount = 0;

    this.bark = function() {
        barkCount++;
        alert(this.name + " bark");
    };

    this.getBarkCount = function() {
        alert(this.name + " has barked " + barkCount + " times");
    };
};

Dog.prototype.wagTail = function() {
    alert(this.name + " wagging tail");
};

var dog = new Dog("Dave");
dog.bark();
dog.bark();
dog.getBarkCount();
dog.wagTail();

Solution 2 - Javascript

The two are different: The first one will store the reference to the method only on the prototype object whereas the second solution will store the method on each of the object. This means that each object will contain an extra pointer and thus take up a bit more memory each.

The per-object method allows the method to refer to variables in the constructor (a closure) and it therefore allows you to access some data that you cannot access from a prototype methods.

Finally, a prototype method can be changed later, that is you can redefine Bark at runtime on the prototype object, and this change will work for all objects with this prototype (since the method is always looked up through the prototype).

Solution 3 - Javascript

The vast majority of javascript code that I've seen uses the prototype method. I think that there are three reasons for this that I can think of off the top of my head.

The first is that you avoid having every class be a huge constructor: constructor logic goes in the constructor function, logic for other methods is declared elsewhere--this is mostly a clarity thing / separation of concerns thing, but in javascript you need every bit of clarity you can get your hands on.

The second is efficiency. When you declare methods in the constructor, you are creating a new instance of the function object for each instance of the object, and also binding the scope of the constructor to each of these functions (that is, they can reference, for example, the arguments to the constructor, which can then never be gc'd as long as the object lives). When you declare methods on the prototype there is a single copy of the function object that is used by all instances--prototype properties are not copied onto instances.

A third reason is that you can "extend" a class in various ways when you use the prototype method, such as the prototype chaining used by Backbone.js and CoffeeScript's class construct.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoe AlfanoView Question on Stackoverflow
Solution 1 - JavascriptTim DownView Answer on Stackoverflow
Solution 2 - JavascriptMathias SchwarzView Answer on Stackoverflow
Solution 3 - JavascriptjjmView Answer on Stackoverflow