Object oriented javascript with prototypes vs closures

JavascriptOop

Javascript Problem Overview


I'm curious what the difference is between the following OOP javascript techniques. They seem to end up doing the same thing but is one considered better than the other?

function Book(title) {
    this.title = title;
}

Book.prototype.getTitle = function () {
    return this.title;
};

var myBook = new Book('War and Peace');
alert(myBook.getTitle())

vs

function Book(title) {
    var book = {
        title: title
    };
    book.getTitle = function () {
        return this.title;
    };
    return book;
}

var myBook = Book('War and Peace');
alert(myBook.getTitle())

Javascript Solutions


Solution 1 - Javascript

The second one doesn't really create an instance, it simply returns an object. That means you can't take advantage of operators like instanceof. Eg. with the first case you can do if (myBook instanceof Book) to check if the variable is a type of Book, while with the second example this would fail.

If you want to specify your object methods in the constructor, this is the proper way to do it:

function Book(title) {
    this.title = title;

    this.getTitle = function () {
        return this.title;
    };
}

var myBook = new Book('War and Peace');
alert(myBook.getTitle())

While in this example the both behave the exact same way, there are differences. With closure-based implementation you can have private variables and methods (just don't expose them in the this object). So you can do something such as:

function Book(title) {
    var title_;

    this.getTitle = function() {
        return title_;
    };

    this.setTitle = function(title) {
        title_ = title;
    };

    // should use the setter in case it does something else than just assign
    this.setTitle(title);
}

Code outside of the Book function can not access the member variable directly, they have to use the accessors.

Other big difference is performance; Prototype based classing is usually much faster, due to some overhead included in using closures. You can read about the performance differences in this article: http://blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx

Solution 2 - Javascript

Which is better can sometimes be defined by the context of their usage.

Three constraints of how I choose between Prototype and Closure methods of coding (I actively use both):

  1. Performance/Resources
  2. Compression requirements
  3. Project Management

1. Performance/Resources

For a single instance of the object, either method is fine. Any speed advantages would most likely be negligible.

If I am instantiating 100,000 of these, like building a book library, then the Prototype Method would be preferred. All the .prototype. functions would only be created once, instead of these functions being created 100,000 times if using the Closure Method. Resources are not infinite.

2. Compression

Use the Closure Method if compression efficiency is important (ex: most browser libraries/modules). See below for explanation:

Compression - Prototype Method

function Book(title) {
    this.title = title;
}

Book.prototype.getTitle = function () {
  return this.title;
};

Is YUI compressed to

function Book(a){this.title=a}Book.prototype.getTitle=function(){return this.title};

A savings of about 18% (all spaces/tabs/returns). This method requires variables/functions to be exposed (this.variable=value) so every prototype function can access them. As such, these variables/functions can't be optimized in compression.

Compression - Closure Method

function Book(title) {
  var title = title; // use var instead of this.title to make this a local variable

this.getTitle = function () {
  return title;
};
}

Is YUI compressed to

function Book(a){var a=a;this.getTitle=function(){return a}};

A savings of about 33%. Local variables can be optimized. In a large module, with many support functions, this can have significant savings in compression.

3. Project Management

In a project with multiple developers, who could be working on the same module, I prefer the Prototype Method for that module, if not constrained by performance or compression.

For browser development, I can override the producton.prototype.aFunction from "production.js" in my own "test.js" (read in afterwords) for the purpose of testing or development, without having to modify the "production.js", which may be in active development by a different developer.

I'm not a big fan of complex GIT repository checkout/branch/merge/conflict flow. I prefer simple.

Also, the ability to redefine or "hijack" a module's function by a testbench can be beneficial, but too complicated to address here...

Solution 3 - Javascript

The former method is how JavaScript was intended to be used. The latter is the more modern technique, popularised in part by Douglas Crockford. This technique is much more flexible.

You could also do:

function Book(title) {
    return {
        getTitle: function () {
            return title;
        }
    }
}

The returned object would just have an accessor called getTitle, which would return the argument, held in closure.

Crockford has a good page on Private Members in JavaScript - definitely worth a read to see the different options.

Solution 4 - Javascript

It's also a little bit about re-usability under the hood. In the first example with the Function.prototype property usage all the instances of the Book function-object will share the same copy of the getTitle method. While the second snippet will make the Book function execution create and keep in the heap 'bookshelf' different copies of the local closurable book object.

function Book(title) {
    var book = {
        title: title
    };
    book.getTitle = function () {
        return this.title += '#';
    };
    return book;
}

var myBook = Book('War and Peace');
var myAnotherBook = Book('Anna Karenina');
alert(myBook.getTitle()); // War and Peace#
alert(myBook.getTitle()); // War and Peace##
alert(myAnotherBook.getTitle()); // Anna Karenina#
alert(myBook.getTitle());// War and Peace###

The prototype members exist in the only copy for all the new instances of the object on the other hand. So this is one more subtle difference between them that is not very obvious from the first sigh due to the closure trick.

Solution 5 - Javascript

here is an article about this in general Book inharets from Book.prototype. In first example you add function to getTitle Book.prototype

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
QuestionDavidView Question on Stackoverflow
Solution 1 - Javascriptreko_tView Answer on Stackoverflow
Solution 2 - JavascriptJ. McNerneyView Answer on Stackoverflow
Solution 3 - JavascriptSkilldrickView Answer on Stackoverflow
Solution 4 - JavascriptArmanView Answer on Stackoverflow
Solution 5 - JavascripttsinikView Answer on Stackoverflow