Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In Javascript there are a few clearly prominent techniques for create and manage classes/namespaces in javascript.

I am curious what situations warrant using one technique vs. the other. I want to pick one and stick with it moving forward.

I write enterprise code that is maintained and shared across multiple teams, and I want to know what is the best practice when writing maintainable javascript ?

I tend to prefer Self-Executing Anonymous Functions however I am curious what the community vote is on these techniques.

Prototype :

function obj()
{
}

obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();

Self-Closing Anonymous Function :

//Self-Executing Anonymous Function 
(function( skillet, $, undefined ) {
    //Private Property
    var isHot = true;

    //Public Property
    skillet.ingredient = "Bacon Strips";

    //Public Method
    skillet.fry = function() {
        var oliveOil;

        addItem( "\t\n Butter \n\t" );
        addItem( oliveOil );
        console.log( "Frying " + skillet.ingredient );
    };

    //Private Method
    function addItem( item ) {
        if ( item !== undefined ) {
            console.log( "Adding " + $.trim(item) );
        }
    }     
}( window.skillet = window.skillet || {}, jQuery ));   
//Public Properties      
console.log( skillet.ingredient ); //Bacon Strips  

//Public Methods 
skillet.fry(); //Adding Butter & Fraying Bacon Strips 

//Adding a Public Property 
skillet.quantity = "12"; console.log( skillet.quantity ); //12   

//Adding New Functionality to the Skillet 
(function( skillet, $, undefined ) {
    //Private Property
    var amountOfGrease = "1 Cup";

    //Public Method
    skillet.toString = function() {
        console.log( skillet.quantity + " " + 
                     skillet.ingredient + " & " + 
                     amountOfGrease + " of Grease" );
        console.log( isHot ? "Hot" : "Cold" );
     };     

}( window.skillet = window.skillet || {}, jQuery ));
//end of skillet definition


try {
    //12 Bacon Strips & 1 Cup of Grease
    skillet.toString(); //Throws Exception 
} catch( e ) {
    console.log( e.message ); //isHot is not defined
}

I feel that I should mention that the Self-Executing Anonymous Function is the pattern used by the jQuery team.

Update When I asked this question I didn't truly see the importance of what I was trying to understand. The real issue at hand is whether or not to use new to create instances of your objects or to use patterns which do not require constructors/use of the new keyword.

I added my own answer, because in my opinion we should make use of patterns which don't use the new keyword.

For more information please see my answer.

share|improve this question
1  
can you give short examples of the two techniques you are describing? –  Hey Jan 6 '12 at 3:48
    
Don't underestimate prototype because of my simple sample. –  Robotsushi Jan 6 '12 at 3:59
1  
it's not executing itself =/ –  Hey Jan 6 '12 at 4:06
2  
i don't see any parentheses to close the expression or call it... –  Hey Jan 6 '12 at 4:18
1  
(+1) Namespaces are overlooked for many developers. –  umlcat Feb 3 '12 at 19:57
show 8 more comments

7 Answers 7

Self executing anonymous functions are used to automate script execution without hooking into external events (i.e. window.onload).

In this example it is used to form the classic Module pattern, the primary purpose of which is to introduce a namespace into the global environment, and provide encapsulation for any internal properties that are not "exported" or attached to the namespace.

Modifying an objects prototype, on the other hand, is used to establish inheritance (or extend natives). This pattern is used to produce 1:n objects with common methods or properties.

You should not choose one pattern in preference to the other, since they perform different tasks. In terms of namespacing, the Self Executing Function is an appropriate choice.

share|improve this answer
6  
Note that "self executing anonymous functions" are commonly known as immediately-invoked function expressions (IIFE). –  voithos Jan 23 at 0:46
add comment

Here's the pattern that I just began using (have been using variations of it up until yesterday):

function MyClass() {
    // attributes
    var privateVar = null;

    // function implementations
    function myPublicFunction() {
    }

    function myPrivateFunction() {
    }

    // public declarations
    this.myPublicFunction = myPublicFunction;
}

MyClass.prototype = new ParentClass(); // if required

A few thoughts on this:

  1. You shouldn't get any (anonymous) traces in your debugger stack traces as everything's named (no anonymous functions).
  2. It's the cleanest pattern that I've seen yet
  3. You're able to easily group up your exposed API without having their implementations coupled to the declaration (meaning someone can easily grok your public class interface without having to scroll)

The only time that I'd use prototype anymore really is to define inheritance.

share|improve this answer
4  
There are a few problems with this. A new function object is created for each "method" with each invocation of the constructor. Also, calling a constructor to get a copy of prototype object for inheritance is frowned on. Use Object.create(ParentClass.prototype), or a shim for Object.create like function clone(obj){return this typeof 'clone' ? this : new clone(clone.prototype=obj)} –  Hey Jan 6 '12 at 5:04
    
@GGG: Yes, you're correct with your first point. I'd say (and should have mentioned in my post) that each specific use case of an implementation should be thought through. My issue with prototype method as you suggest is (unless there's a method that I'm unfamiliar with, which may be the case) that you lose the ability to encapsulate attributes, meaning everything's open as public (which isn't the end of the world, just a personal preference). –  Demian Brecht Jan 7 '12 at 22:14
    
Also, after viewing the following work done on jsperf (jsperf.com/object-create-vs-constructor-vs-object-literal/12), I would take the performance increase over memory cost of additional copies almost any day (again, very subjective to the specific use case). –  Demian Brecht Jan 7 '12 at 22:16
    
Now, having said all that, I'm only partway through ECMA-262, so there may be a bunch of stuff that I'm not seeing.. Also, I don't take Crockford's word as gospel.. Yes, he's one of the experts in the field (one of the foremost of course), but it doesn't always make him 100% right at all times. There are other experts out there (me not being one of them ;)) who have contradictory opinions with compelling arguments. –  Demian Brecht Jan 7 '12 at 22:18
2  
you might be interested in this thing I'm working on. –  Hey Jan 7 '12 at 22:43
show 1 more comment

I use prototypes because they are cleaner and follow standard inheritance patterns. Self-invoking functions are great for browser development or a situation where you don't know where the code is being executed, but otherwise it's just noise.

Example:

var me;

function MyObject () {
    this.name = "Something";
}

MyObject.prototype.speak = function speak () {
    return "Hello, my name is " + this.name;
};

me = new MyObject();
me.name = "Joshua";
alert(me.speak());
share|improve this answer
1  
Self executing anonymous functions are very useful for allowing you have private functions accessible to a class. –  Zee Jan 7 '12 at 20:28
add comment

Live Example

(function _anonymouswrapper(undefined) {

    var Skillet = {
        constructor: function (options) {
            options && extend(this, options);
            return this; 
        },
        ingredient: "Bacon Strips",
        _isHot: true,
        fry: function fry(oliveOil) {
            this._addItem("\t\n Butter \n\t");
            this._addItem(oliveOil);
            this._addItem(this.ingredient);
            console.log("Frying " + this.ingredient);
        },
        _addItem: function addItem(item) {
            console.log("Adding " + item.toString().trim());
        }
    };

    var skillet = Object.create(Skillet).constructor();

    console.log(skillet.ingredient);
    skillet.fry("olive oil");

    var PrintableSkillet = extend(Object.create(Skillet), {
        constructor: function constructor(options) {
            options && extend(this, options);
            return this;
        },
        _amountOfGrease: "1 Cup",
        quantity: 12,
        toString: function toString() {
            console.log(this.quantity + " " +
                        this.ingredient + " & " +
                        this._amountOfGrease + " of Grease");
            console.log(this._isHot ? "Hot" : "Cold");
        }
    });

    var skillet = Object.create(PrintableSkillet).constructor();

    skillet.toString();

    function extend(target, source) {
        Object.getOwnPropertyNames(source).forEach(function (name) {
            var pd = Object.getOwnPropertyDescriptor(source, name);
            Object.defineProperty(target, name, pd);
        });
        return target;
    }
}());

You can use a IIFE to emulate "module scope" around your code. Then you can just use objects as you normally do.

Don't "emulate" private state using closures as that has a large memory penalty.

If your writing an enterprise application and want to keep your memory usage under 1GB avoid unnecessarily using closures to store state.

share|improve this answer
    
You've got a couple of typos in the code mate. I'm not positive about your assertion of closures automatically causing excessive memory usage either, I think it depends on how heavily you use them and how well you're dealing with scoping issues (mixing things from inside a closure with things from outside is generally bad, for example (your usage of the global console is a good example of this, the above code would be much more efficient if you passed in console as a variable)). –  Ed Woodcock Jan 6 '12 at 11:59
    
@EdWoodcock I figured the code was buggy, just refactored and fixed it. –  Raynos Jan 6 '12 at 12:01
    
@EdWoodcock the efficiency difference between local console and global console is a micro optimisation. It is worth doing so you can minimize console but that's a different matter –  Raynos Jan 6 '12 at 12:04
    
@EdWoodcock closures are slow if your duplicating objects in them. What's slow is creating functions inside functions when it's not needed. closures also have small memory overhead for storing state in comparison to storing state on objects directly –  Raynos Jan 6 '12 at 12:05
    
Yeah, just wanted to point it out since your answer is a reasonable way of going about things (albeit not the way I'd choose to use). (I'd have done an edit but I'm still not sure about the etiquette of those on this particular SE site). –  Ed Woodcock Jan 6 '12 at 12:05
show 5 more comments

I'd go with the self-executing function, but with a slight difference:

MyClass = (function() {
     var methodOne = function () {};
     var methodTwo = function () {};
     var privateProperty = "private";
     var publicProperty = "public";

     return function MyClass() {
         this.methodOne = methodOne;
         this.methodTwo = methodTwo;
         this.publicProperty = publicProperty;
     };
})();

If find this approach much cleaner, as I separate the returned global variable from any input parameters (such as jQuery) (the way you wrote it is equivalent to returning void and using a ref parameter in C#, which I find a bit off, or passing in a pointer to a pointer and re-assigning it in C++). If I were then going to attach additional methods or properties to the class I would use prototypal inheritance (example with jQuery's $.extend method, but it's easy enough to roll your own extend()):

var additionalClassMethods = (function () {
    var additionalMethod = function () { alert('Test Method'); };
    return { additionalMethod: additionalMethod };
})();

$.extend(MyClass.prototype, additionalClassMethods);

var m = new MyClass();
m.additionalMethod(); // Pops out "Test Method"

This way you have a clear distinction between the added methods and the original ones.

share|improve this answer
1  
Am I the only one who thinks using NFEs like this is a bad idea? –  Hey Jan 6 '12 at 22:34
add comment
up vote 0 down vote accepted

Update I now have a much better understanding of javascript and feel I can properly address the question. I think it was a poorly worded, but very important javascript topic to address.

The Self Executing Anonymous Function pattern is not one which requires use of the new keyword if you avoid the use of this outside of functions. I agree with the idea that using new is an old technique and we should instead strive to use patterns that avoid the use of new.

The Self Executing Anonymous Function meets this criteria.

The answer to this question is subjective, because there are so many coding styles in javascript. However based on my research and experience I would recommend choosing to use the Self Executing Anonymous Function to define your API's and avoid the use of new whenever possible.

share|improve this answer
    
What is bad about the new keyword? I'm curious. –  Ally Jan 23 at 9:31
add comment

Here is how I would go about this IIFE SelfExecutingFunction to extend the Myclass with Myclass.anotherFunction();

MyClass = (function() {
     var methodOne = function () {};
     var methodTwo = function () {};
     var privateProperty = "private";
     var publicProperty = "public";

    //Returning the anonymous object {} all the methods and properties are reflected in Myclass constructor that you want public those no included became hidden through closure; 
     return {
         methodOne = methodOne;
         methodTwo = methodTwo;
         publicProperty = publicProperty;
     };
})();

@@@@@@@@@@@@@@@@@@@@@@@@
//then define another IIFE SEF to add var function=anothermethod(){};
(function(obj){
return obj.anotherfunction=function(){console.log("Added to Myclass.anotherfunction");};
})(Myclass);

//the last bit : (function(obj){})(Myclass); obj === Myclass obj is an alias to pass the Myclass to IIFE

var myclass = new Myclass();
myclass.anotherfunction(); //"Added to Myclass.anotherfunction"
share|improve this answer
1  
Programmers is tour conceptual questions answers are expected to explain things. Throwing code dumps instead of explanation is like copying code from IDE to whiteboard: it may look familiar and even sometimes be understandable, but it feels weird... just weird. Whiteboard doesn't have compiler –  gnat Jan 23 at 2:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.