views:

76

answers:

2

I want to check in a script if a certain other module is already loaded.

if (ModuleName) {
    // extend this module
}

But if ModuleName doesn't exist, that throws.

If I knew what the Global Object was I could use that.

if (window.ModuleName) {
    // extend this module
}

But since I want my module to work with both browsers and node, rhino, etc, I can't assume window.

As I understand it, this doesn't work in ES5 with "use strict";

var MyGLOBAL = (function () {return this;}()); // MyGlobal becomes null

This will also fail with a thrown exception

var MyGLOBAL = window || GLOBAL

So it seems like I'm left with

try {
    // extend ModuleName
} catch(ignore) {}

None of these cases will pass JSLint.

Am I missing anything?

+4  A: 

Well, you can use the typeof operator, and if the identifier doesn't exist in any place of the scope chain, it will not throw a ReferenceError, it will just return "undefined":

if (typeof ModuleName != 'undefined') {
  //...
}

Remember also that the this value on Global code, refers to the global object, meaning that if your if statement is on the global context, you can simply check this.ModuleName.

About the (function () { return this; }()); technique, you are right, on strict mode the this value will simply be undefined.

As far I remember, under strict mode the only way to get a reference to the Global object, no matter where you are, is through an indirect eval call, for example:

"use strict";
var get = eval;
var global = get("this");

The above will work because in ES5, indirect calls to eval, use the global environment as both, the variable environment and lexical environment for the eval code.

See details on Entering Eval Code, Step 1.

But be aware that the above solution will not work on ES3 implementations, because an indirect call to eval on ES3 will use the variable and lexical environments of the caller as the environments for the eval code itself.

And at last, you may find useful to detect if strict mode is supported:

var isStrictSupported = (function () { "use strict"; return !this; })();
CMS
+1  A: 

Here you go :)

var globalObject = (function(){return this;})();

This should work from anywhere, for example from within another closure.

Edit - just read your post more carefully and saw the part about ES5 strict mode. Can anyone shed some more light on that? This has been the accepted way to get the the global object for as long as I can remember... I sure hope it doesn't end up getting broken.

Edit 2 - CMS' answer has more info on ES5 strict mode's treatment of this.

no