0

I'm trying to use a modular namespace pattern which allows me to expand the functions available within various namespaces and define them across multiple files. This is the pattern I'm using;

var Namespace = Namespace || {};

Namespace.SubSpace = (function () {
    var subspace = {};

    subspace.Func = function () {
        return "My Function";
    };

    return subspace;
})();

How can I make my namespace functions available prior to their definition? In other words how can I call Namespace.SubSpace.Func() without it relying on the function declaration having already been parsed?

Red Taz
  • 4,159
  • 4
  • 38
  • 60
  • 3
    You cannot. Why would you need that? – Bergi Jan 22 '14 at 16:41
  • 1
    Are you aware that in your example, you are immediately executing the function and Namespace.SubSpace.Func is in fact undefined? – Felix Kling Jan 22 '14 at 16:44
  • @Bergi I'd like to bundle accompanying scripts as part of a WebForms component library, so there is no guarantee that the library javascript will have been included prior to user scripts. The question is inspired by Microsoft's approach `Sys.WebForms` – Red Taz Jan 22 '14 at 16:47
  • Never heard about 'modular namespace' pattern. Could you add a reference? – Pavlo Jan 22 '14 at 16:47
  • @RedTaz: As long as the userscripts don't *use* your libary before it is included, that's no problem. If they try, there's nothing you can do against - you will need to find a way to guarantee that is's included before them (ask a more specific question about that). – Bergi Jan 22 '14 at 16:52
  • @FelixKling I hadn't realised that no, I've edited the question thanks for pointing it out – Red Taz Jan 23 '14 at 08:41
  • @Pavlo I don't think it's a recognised pattern, it's just 'a namespace pattern' which seems to me to be modular – Red Taz Jan 23 '14 at 08:44
  • Even after edit `Namespace.SubSpace.Func` still not a function, but plain object. – Pavlo Jan 23 '14 at 09:57

1 Answers1

0

I can get close enough to solving my problem by using an approach similar to JQuery's ready() function. However, it does rely on defining the root namespace before anything else. The root namespace also includes functionality which allows callbacks to be registered.

var Namespace = (function () {

    var namespace = {};
    namespace.ReadyCallbacks = [];

    namespace.Ready = function (callback, queueJump) {
        if (queueJump)
            namespace.ReadyCallbacks.unshift(callback);
        else
            namespace.ReadyCallbacks.push(callback);
    };

    namespace.Begin = function () {
        for (x = 0; x < namespace.ReadyCallbacks.length; x++) {
            namespace.ReadyCallbacks[x]();
        }
    };

    return namespace;
})();

Importantly this distinguishes between callbacks which should run before others. This allows framework modules to define sub-namespaces and functions before user scripts are executed. (Even if user scripts are loaded first).

User Scripts

Namespace.Ready(function () {
    console.log(Namespace.SubSpace.Func()); // prints "Module 1"
});

Framework Module

Namespace.Ready(function () {
    Namespace.SubSpace = (function () {
        var subspace = {};

        subspace.Func = function () {
            return "Module 1";
        };

        return subspace;
    })();
}, true);

Finally, calling Namespace.Begin() executes everything in the correct order. Also, since I'm using JQuery anyway, I can wrap this in $(document).ready().

I'm not terribly proficient in javascript so I'm not sure how 'correct' this approach is, I'd welcome comments & suggestions.

Red Taz
  • 4,159
  • 4
  • 38
  • 60