0

Possible Duplicate:
Use of ‘prototype’ vs. ‘this’ in Javascript?

I am reading this blog post about making JS frameworks. I am familiar (to an extent) with the concepts of ECMA prototype, and scope and closures in general. However I'm not confident that I am sure about the ins and outs of code like the following:

var myFramework = (function (window, document) {
    var /* Global variables */

    myFramework = function (el, options) {
        // code
    };

    myFramework.prototype = {
        // code
    };

    return myFramework;
})(window, document);

I understand why window and document are being passed (to save on resources, as explained in this video). What boggles me especially is why is it necessary to have both myFramework = function () {} and myFramework.prototype? What is it for? Why not use this declarations inside myFramework = function () {} instead?

Community
  • 1
  • 1
pilau
  • 6,635
  • 4
  • 56
  • 69
  • 1
    What do you mean by *"the separation with `myFramework.prototype`"*? And use `this` instead of *what*? – I Hate Lazy Oct 25 '12 at 14:49
  • 1
    It's needed so that each instance of `myFramework` will share the same prototype methods. They would be copied for each instance if you used `this.method`. this is why they are called `ownProperties`. What you assign to prototype are *common properties*. – dfsq Oct 25 '12 at 14:49
  • If you are coming from a class-based inheritance model, you can think of prototype methods as static. Creating a method on the prototype creates it for all objects that extend that prototype. In your example, the `this` statement would refer to the function instance, which is quite different from the prototype. –  Oct 25 '12 at 14:57
  • 1
    @atonparker I don't feel like that's a very good analogy. Methods on the prototype don't behave statically at all, they interact with and have access to the object's internals. A method like `myFramework.foo = function() {}` is much more of a "static" method. – Matt Greer Oct 25 '12 at 15:14
  • @Matt Greer but `myFramework.foo = function() {}` can also be a prototype method, can't it? To everyone, I edited the question. hopefully I am more clear now. Thanks. – pilau Oct 25 '12 at 15:35
  • @pilau it can, but that changes how the function gets invoked and what can invoke it. – Matt Greer Oct 25 '12 at 15:49
  • @pilau Matt is correct, prototype functions operate on the instance and aren't like static methods at all. `myFramework.foo = function() { }` creates an instance function. `myFramework.foo()` will call the instance function if it exists, or the prototype function if it doesn't. –  Oct 25 '12 at 16:00
  • That I do understand. But from the comments above it seems this is _not_ the only reason to use prototype? Edit: I will be reading [this](http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjavascript) now. – pilau Oct 25 '12 at 16:08

1 Answers1

1

In javascript, the prototype object (In your case myFramework.prototype) allows all instances of the class to share the same methods and properties. For example:

myFramework.prototype = {
    version: "0.0.1",
    fancyMethod: function(){//...//}
};

//...// Somewhere else in code.

var framework = new myFramework();
var framework2 = new myFramework();

framework.version; // ---> "0.0.1"
framework2.version; // ---> "0.0.1"

//What if?
myFramework.prototype.version = "0.0.2";
framework.version; // ---> "0.0.2"
framework2.version; // ---> "0.0.2" //This will surprise most developers.

This is because if the property isn't on the immediate instance, it looks in the prototype object for the property or method. But once a property is set to an instance it no longer looks up the prototype chain to find the value. For Example.

framework.version = "0.0.3";

framework2.version; // ---> "0.0.2" Still looks up the prototype chain.
framework.version; // ---> "0.0.3" Now it finds the property on the instance.

The prototype object is mostly used for methods. It gets a bit confusing when using properties on a prototype object.

I believe the best example of how this is being used is with jQuery. If I'm correct, the jQuery.fn is equal to the jQuery.prototype. This is how any previously created instances of jQuery get the newly assigned methods. Its an interesting concept, but hard to understand when to use it.

The prototype object gives you the power to augment all instances on the fly with new methods and properties (even if the instances have been created), that don't need to be assigned on the creation of the instance.

Here is an example on jsFiddle

  • So therefore, if I am not intending the framework to have multiple instances, does it render prototype unnecessary? – pilau Oct 25 '12 at 16:56
  • Yes. If I understand you correctly it sounds like you would like to have a singleton. I would simply use a object literal in that case, or do what you suggested by having the methods assigned during construction. Also if you create a class for the singleton I would return the instance of the class, not the class itself. – jaredjbarnes Oct 25 '12 at 17:47
  • @jaredbarnes What do you mean by return the instance of the class? Please compare with my code here: http://jsfiddle.net/pilau/G4NLT/ – pilau Oct 25 '12 at 18:59
  • Here are the two ways that I would approach it. http://jsfiddle.net/jaredjbarnes/CMtHy/ – jaredjbarnes Oct 26 '12 at 03:36
  • Fantastic. Now I know I am not missing anything. Yesterday I eventually went for the object literal, but I did it this way: `Singleton = (function(window, document, undefined) { /* blah blah */ return singletonObjectLiteral; })()` which is basically the same. Thank you! P.S. This is called the module pattern, by the way. – pilau Oct 26 '12 at 08:33