20

Answer Embedded Below in UPDATE 2/ANSWER

Thanks to Joseph for helping me find the answer (even though I don't like it =).

ORIGINAL QUESTION

While doing some research on best practices when using Namepsaces in JavaScript, I came across this definition of the "Model Pattern": http://yuiblog.com/blog/2007/06/12/module-pattern/ .

I've been generally using this pattern since I saw it in YUI2 years ago, and this article gives a nice overview of the concept. But what it does not touch on is why "Self Executing Anonymous Functions" are used in place of "new function". This was asked in the comments, but was not well described by the author. As this article is 4+ years old (and I've not found the answer elsewhere online) I thought I'd bring it here.

It's already within a closure, so? (see: Why is this function wrapped in parentheses, followed by parentheses? which also doesn't answer my question =).

Assuming the following setup code..

var MyNamespace = window.MyNamespace || {};

Which of these is preferred and why?

MyNamespace.UsingNew = new function() {
    var fnPrivate = function() {
        return "secrets1";
    };

    this.property = "value1";
    this.method = function() {
        return "property = " + this.property + ' ' + fnPrivate();
    }
};

MyNamespace.UsingSelfEx = (function() { //# <- Added "pre-parens" suggested by chuckj
    var fnPrivate = function() {
        return "secrets2";
    };
    var fnReturn = {};

    fnReturn.property = "value2";
    fnReturn.method = function() {
        return "property = " + this.property + ' ' + fnPrivate();
    }

    return fnReturn;
})();

UPDATE:

It seems that like jQuery, all the cool kids are using "Self Executing Anonymous Functions" (SEAF)! But I just don't get this, as I find it much cleaner to use the .UsingNew approach as you expose the public functions at definition (rather than below in a return that needs to be maintained separately or being forced to use the inline object notation).

The argument for not needing "that = this" doesn't hold water for me for a number of reasons:

  • In order to avoid "var that = this" you end up either making a "var obj" plus a return statement (having to maint. a separate definition of what is public) or being forced to use the inline object notation (return {1,2,3}) for your public properties/methods.
  • You could always make a private variable of "var that = this" at the top of the class/namespace and use "that" throughout.

Now... I suppose my development style may well make the .UsingNew pattern much easier to manage. My "private" functions are almost always "static" in nature, so I need to pass in the context anyway (supplanting the need for "this"). I have also taken up the habit of using an "abbreviation" namespace, so when I do need access to "this" I simply refer to the full object via the "abbreviation" namespace rather than via it's full path. E.G.:

var PrivateFunct = function() {
    var rThis = Cn._.val; //# The abbreviated form of Cn.Renderer.Form.Validation
    //...
};

or if it's a Private Static Function...

var PrivateStaticFunct = function(oContext) {
    //...
};

Other then the reasons given above, I personally find the .UsingNew approach much more readable in the source. I've got a pretty extensive codebase that uses the .UsingNew pattern here: http://code.google.com/p/cn-namespace/source/browse/Cn.Web/js/Cn/ with the Validation functionality probably the easiest to get your head around in 1 quick read thru. I also use some SEAF functions (see ErrorMessages.js.aspx) but only when they make sense.

I could not imagine having to maintain separate returns to expose the public interfaces at the bottom! Yuck!

Now, don't get me wrong, there are a number of places where a SEAF is very useful in order to enforce the closure, but I personally think it's overused within objects.

UPDATE 2:

Upon further reflection (and thanks to an extended discussion with Joseph under his answer) there seems to be some rules that can be applied to this DEATHMATCH:

Per Douglas Crockford (see: JS we hardly new Ya) Anonymous functions should never use the "new" keyword because:

  • It is faster to use an object literal.
  • By using new to invoke the function, the object holds onto a worthless prototype object. That wastes memory with no offsetting advantage. If we do not use the new, we don’t keep the wasted prototype object in the chain. (NOTE: prototype calls come after the constructor definition, and as SEAF or "new" anonymous functions are fired imminently one cannot use prototype with them)
  • It requires less code to use an object literal. (while true, I have to disagree as I hate the object literal notation, I'd much prefer to use ;'s rather then ,'s as it's more readable).
  • It is never a good idea to put new directly in front of function. For example, new function provides no advantage in constructing new objects.

So it seems the meat and potatoes of the matter is this: SEAF's are preferable to var obj = new function() {...}; due to speed and less overhead (no unneeded prototype object). What you have to suffer through is the fact that you are forced to use object literal notation (so ,'s rather than ;'s between your public members) or to maintain a separate list of public objects in a return object.

SEAF's are not advisable when you are intending the function to work as an object constructor as instanceof will not work as expected (see: creating objects from JS closure: should i use the “new” keyword?).

ANSWER:

  • If it's an anonymous function intended to function as a Singleton/Global Static Instance, use SEAF.
  • If you are intending it to function as a Constructor (to potentially represent multiple objects) or you are using .prototype, use a "standard" function definition and invoke with "new", e.g.:

    function PseudoClass1() {}

    var PseudoClass2 = function() {};

    var myClass1 = new PseudoClass1();

    var myClass2 = new PseudoClass2();

I have to say, I am not happy with this answer ;) I find the .UsingNew pattern MUCH more readable in the codebase, but it is slower and uses more memory then SEAF due to the fact that the unused prototype reference is instantiated and left in the object chain.

Community
  • 1
  • 1
Campbeln
  • 2,880
  • 3
  • 33
  • 33
  • 1
    (Late to the party I know..) A lot of interesting stuff here...since you strongly prefer the UsingNew I don't think the unused prototype alone is sufficient reason to change your approach...it's a very minimal amount of memory (for sake of comparison, it's much more minimal than the amount that coders using the module pattern are willing to sacrifice by not using prototypes.) – Matt Browne May 12 '13 at 09:18
  • 1
    In terms of the anonymous function approach, perhaps it would seem more readable if you called the return variable "self" instead of something like "fnReturn." You could even pass any empty object to the function and have "self" be a parameter; then asside from the return statement and the use of "self" instead of "this", the body of the function would be identical to your first example. – Matt Browne May 12 '13 at 21:29
  • You should [definitely not use `new function`](http://stackoverflow.com/a/10406585/1048572) – Bergi Jan 26 '15 at 02:11

3 Answers3

8

For one thing, this pattern:

MyNamespace.UsingNew = new function() {
    var fnPrivate = function() {

        //what's this in here?

        return "secrets1";
    };

    this.property = "value1";
    this.method = function() {

        //what's this in here?

        return "property = " + this.property + ' ' + fnPrivate();
    }
};
  • uses the "new" keyword to create an instance of an object, which is modeled using a constructor function. forgetting to use "new", you'll end up named making a function MyNamespace.UsingNew() instead of an object.

  • it's a constructor function, and not yet an object's instance (until you build it using new). you need to use "this" to pertain the object that it will become. it just add's problems to scope, especially when you nest more functions in it, and the value of "this" will change from time to time (and you won't see it coming until the console tell's you). familiar with the self=this or that=this to save the value of "this"? it's pretty much seen when using this pattern

on the otherhand, the next pattern is somewhat better (for me) since:

  • you don't need to use "new" since it returns an object.

  • not using "this" since it already returns an object. you don't even need "this".

also, i prefer constructing the other pattern this way:

ns.myobj = (function(){

    //private
    var _privateProp = '';
    var _privateMeth = function(){};

    //public
    var publicProp = '';
    var publicMeth = function(){};

    //expose public
    return {
        prop:publicProp,
        meth:publicMeth
    };
}());
Joseph
  • 117,725
  • 30
  • 181
  • 234
  • Forgive my ignorance, but even if you forget the "new" keyword and returned a function rather than an object, what is the difference? I'm guessing functionality not much but performance(ly) bad? As to your pref. method, don't you find it a maint. nightmare with the return at the bottom? I've always used ".UsingNew" see: [link](http://code.google.com/p/cn-namespace/source/browse/Cn.Web/js/Cn/Renderer/Form/Form.js) and as to the that = this issue, since I build in Namespaces I just fully address the required functions. I find this less of a pain than maint. that return. – Campbeln Mar 20 '12 at 22:27
  • take a look at this question, where i asked if when to use "new" http://stackoverflow.com/q/9304473/575527 – Joseph Mar 20 '12 at 22:48
  • if you return a function rather than an object, you won't be able to use that object because you haven't built it. you just "defined" a function to that variable instead of building an object for that variable. – Joseph Mar 20 '12 at 22:50
  • Agh... I've probably been bit by that before and simply fixed it with "new" without giving it much thought then =) Thanks again! As to the use of "new", I read this yesterday (and re-reading it now), it has some great info on when and when not to use "new": [JS, We hardly new Ya](http://www.yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/) – Campbeln Mar 20 '12 at 23:26
  • yup, it was one of crockford's videos that discouraged me to use the "new" – Joseph Mar 20 '12 at 23:38
  • Excellent Q&A at [http://stackoverflow.com/q/9304473/575527](http://stackoverflow.com/q/9304473/575527), thanks for that! But I can't help but find that it reaffirms my approach =) Within my referenced codebase, all of the `Cn.blah.Whatever = new function() {...}`'s build Singleton's (I'd say Global Static Instances, but hey!) so I'm basically doing `var myConstructor = new Constructor();` at definition. So in that case... why do you still prefer the SEAF method? – Campbeln Mar 20 '12 at 23:45
  • simple code. you don't see jQuery build objects and plugins using "new" (although it might within it's framework, but you don't see it in the user's code) – Joseph Mar 20 '12 at 23:49
  • Agh... getting it a bit more now... As its an Anonymous Function, the argument is it's smaller code (object literal notation, which I hate, but I digress), faster (per Mr. Crockford), and causes the engine to hang onto an unused prototype object in the chain... (all this from [JS We hardly new Ya](http://www.yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/))... I'll have to chew on this one a bit more... – Campbeln Mar 20 '12 at 23:51
  • @Joseph, I would avoid the publicProp as you used it above because you might be tempted to modify the publicProp captured in the closure which is not the same as prop exposed as a public. This could lead to subtle, hard to find, bugs. – chuckj Mar 21 '12 at 00:20
  • @chuckj that's just an example. i don't actually use public properties. – Joseph Mar 21 '12 at 00:24
  • It's these potential naming differences that freak me out with this specific take on the SEAF! chuckj's approach is more better-er in that regard, but he has to suffer with the object literal notation which is also distracting. The lack of a prototype object in the chain is really an advantage specific to SEAFs, and that seems to be the reason to jump thru these extra hoops =) – Campbeln Mar 21 '12 at 00:39
  • I think you made a syntax error in the last line of the SEAF. Where it says `}());`, I don't see where the function would have been ended previously, although I didn't get an error when I plugged it into a console. The correct syntax is `})();`. Anonymous functions sure can get tricky, eh? – Braden Best Nov 27 '12 at 01:36
  • @B1KMusic Actually, both methods do work and are acceptable. Most developers place the `()` outside to indicate an immediately executed expression. I prefer putting it inside so that I won't accidentally erase them or look weird. – Joseph Nov 27 '12 at 04:07
  • @JosephtheDreamer Hmm.. it's weird that it works, because the first time I tried to write an SEAF, I didn't put parentheses around the entire function definition, and it said something like `unexpected token ( after }`. Lol, no wonder [WTF JS](http://WTFJS.com) is so popular :P – Braden Best Dec 09 '12 at 02:54
  • You should [definitely not use `new function`](http://stackoverflow.com/a/10406585/1048572) – Bergi Jan 26 '15 at 02:10
2

Both are almost identical and should have relatively the same performance characteristics. It is just a matter of style. I, personally, favor the second one but it is written a bit funky. I would write it,

MyNamespace.UsingSelfEx = (function () {
    function fnPrivate() {
        return "secrets2";
    }
    return {
        property: "value2";
        method: function () { 
            return "property = " + this.property + " " + fnPrivate();
        }
    }
})();

You don't really need the parens around the function but self-executing functions normally have them and lets the reader know, at the beginning, that this is a self executing function.

chuckj
  • 27,773
  • 7
  • 53
  • 49
  • Agh, you are correct! Self Executing Functions do generally have the "extra" parens around them! I am quite surprised that this seems to be the preferred method of doing this functionality though. As I use the other method, I occasionally need the "this = that" approach, but I find that FAR less painful than doing the object return in any of it's forms. Plus as I build in Namespaces I generally just refer to the full Namespace address of the this.function I need to use. I do tend to design my "private" functions as "static" so that no doubt helps with the .UsingNew approach. – Campbeln Mar 20 '12 at 22:36
  • See: [link](http://code.google.com/p/cn-namespace/source/browse/Cn.Web/js/Cn/Renderer/Form/Form.js). Oh, and I also employ an "abbreviation" Namespace (represented by "Cn._.*" in the code) to help with the "rThis = Cn._.short" assignments (rather than "rThis = Cn.Some.Long.Namespace.Path"). – Campbeln Mar 20 '12 at 22:37
  • Since this is forming a namespace and will only be executed once this is clearly just a style choice. Pick the one you prefer. I prefer the above but that is just one guys opinion. – chuckj Mar 21 '12 at 00:17
  • Hey chuckj, thanks! But it seems that after some further research there is an advantage to be had with your approach as the unused prototype object is not instantiated and put in the object chain when using an SEAF, where as `new function` does have this extra overhead. So there is a method to your madness =) – Campbeln Mar 21 '12 at 00:33
0

I've seen this and I liked it

var MyThing = (function(){

    function MyThing(args){
    }

    MyThing.prototype = {
        prototypeMethod: function() {}
    };

    return MyThing;
})();

You can also do this

MyThing.create = function(args){
    return new MyThing(args);
}

Usually it is enclosed in an another self invoking function. In order to avoid naming collisions.

(function({

})(window);

And the window object is passed as an argument, to assign it to an upper scope.

window.MyThing = MyThing;

In this example you can use, static variables,private etc.

giannis christofakis
  • 8,201
  • 4
  • 54
  • 65