Javascript Pattern to access the global object [duplicate] - javascript

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 ES 5 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?

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.
Under strict mode there are two ways to get a reference to the Global object, no matter where you are:
Through the Function constructor:
var global = Function('return this')();
Functions created with the Function constructor don't inherit the strictness of the caller, they are strict only if they start their body with the 'use strict' directive, otherwise they are non-strict.
This method is compatible with any ES3 implementation.
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 last 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; })();

Update 2019
With all of today's Webpacks and Broccolis, and Gulps and Grunts, and TypeScripts and AltScripts, and create-react-apps, etc, this is pretty useless, but if you're just working with plain, old, VanillaJS and you want to make it isomorphic, this is probably your best option:
var global
try {
global = Function('return this')();
} catch(e) {
global = window;
}
The Function constructor invocation will work even when using --use_strict in node, as the Function constructor always executes in a global non-strict scope.
If the Function constructor fails, it's because you're in a browser with eval disabled by CSP headers.
Of course, with Deno on the way (the node replacement), they may also disallow the Function constructor, in which case it's back to enumerating objects like global, module, exports, globalThis and window, and then duck-type checking which is the global exhaustively... :-/
Crazy one-line solution (Original):
var global = Function('return this')() || (42, eval)('this');
.
.
.
Works
in every environment (that I tested)
in strict mode
and even in a nested scope
Update 2014-Sept-23
This can now fail if HTTP headers in the latest browsers explicitly forbid eval.
A workaround would be to try / catch the original solution as only browsers are known to run this type of subset of JavaScript.
var global;
try {
global = Function('return this')() || (42, eval)('this');
} catch(e) {
global = window;
}
Example:
---
(function () {
var global = Function('return this')() || (42, eval)('this');
console.log(global);
// es3 context is `global`, es5 is `null`
(function () {
"use strict";
var global = Function('return this')() || (42, eval)('this');
console.log(global);
}());
// es3 and es5 context is 'someNewContext'
(function () {
var global = Function('return this')() || (42, eval)('this');
console.log(global);
}).call('someNewContext');
}());
Tested:
---
* Chrome v12
* Node.JS v0.4.9
* Firefox v5
* MSIE 8
Why:
---
In short: it's some weird quirk. See the comments below (or the post above)
In `strict mode` `this` is never the global, but also in `strict mode` `eval` operates in a separate context in which `this` *is* always the global.
In non-strict mode `this` is the current context. If there is no current context, it assumes the global. An anonymous function has no context and hence in non-strict mode assumes the global.
Sub Rant:
There's a silly misfeature of JavaScript that 99.9% of the time just confuses people called the 'comma operator'.
var a = 0, b = 1;
a = 0, 1; // 1
(a = 0), 1; // 1
a = (0, 1); // 1
a = (42, eval); // eval
a('this'); // the global object

Why just don't simply use this in a global scope as param to a wrapper function, as follows?
(function (global) {
'use strict';
// Code
}(this));

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.

I think this is pretty much okay in rhino, node, browser and with jslint (without additional workaround flags) - would this help? Am I missing something?
x = 1;
(function(global){
"use strict";
console.log(global.x);
}(this));
Though I myself tend to use the window object and if I do need headless testing I can use env.js (rhino) or Phantom (node).

ECMAScript will be adding this to its standard soon:
https://github.com/tc39/proposal-global
Until its done, this is what's recommended:
var getGlobal = function () {
// the only reliable means to get the global object is
// `Function('return this')()`
// However, this causes CSP violations in Chrome apps.
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};

This is not passing jslint: var Fn = Function, global = Fn('return this')();
Try it yourself: http://www.jslint.com/
this will: var Fn = Function, global = new Fn('return this')();
But effectively those are same thing according to MDN:
Invoking the Function constructor as a function (without using the new operator) has the same effect as invoking it as a constructor.

This following solution works in:
Chrome
Node.JS
Firefox
MSIE
Web Workers
The code is:
(function (__global) {
// __global here points to the global object
})(typeof window !== "undefined" ? window :
typeof WorkerGlobalScope !== "undefined" ? self :
typeof global !== "undefined" ? global :
Function("return this;")());
You just need to change X for the name of the variable that you would like to

I had this problem before, I'm not happy with the solution, but it works and passes JSLint (assume browser|assume node):
"use strict";
var GLOBAL;
try{
/*BROWSER*/
GLOBAL = window;
}catch(e){
/*NODE*/
GLOBAL = global;
}
if(GLOBAL.GLOBAL !== GLOBAL){
throw new Error("library cannot find the global object");
}
once you have the GLOBAL var you can do your checking, and at the end of the script type
delete GLOBAL.GLOBAL;

Here's what I am using:
"use strict";
if(this && this.hasOwnProperty && !this.hasOwnProperty('globalScope')){
try {
globalScope = Function('return this')();
}catch(ex){
if(this.hasOwnProperty('window')){
globalScope = window;
}else{
throw 'globalScope not found';
}
}
}

Related

How to check if variable has been declared, although uninitialized?

How to check if a JavaScript variable has actually been declared?
This solution doesn't work in my case:
JavaScript check if variable exists (is defined/initialized)
Example:
(function(){
var abc;
alert(typeof abc === 'undefined') // true
})();
Same as:
(function(){
alert(typeof abc === 'undefined') // true
})();
It produces true in both cases. I could do this:
(function(){
var abc;
var isDefined = false;
try { isDefined = abc || !abc; }
catch(e) {}
alert(isDefined); // true
})();
It works, but I'm looking for anything better that this, x-browsers.
EDIT: I want to use it in a piece of dynamic code which runs via eval and checks if a certain variable exists in either local or global scope.
This question has been asked many times, the answer is "you can't" (other than using try..catch as in the OP).
You can check for properties of an object using in or hasOwnProperty, however both those require that you can access the object that you wish to test. Variables belong to a variable object (ES 3) or environment record (ES 5) of an execution context, and they aren't accessible so you can't check their properties.
The special case is the global object, because global variables (i.e. properties of the global environment record) are made properties of the global object, so you can do:
var global = this;
var foo;
// Declared but not initialised
foo in global // true
global.hasOwnProperty('foo'); // true
// Not declared or initialised
bar in global // error
global.hasOwnProperty('bar'); // true
However, the hasOwnProperty method is not supported on the global object for versions of IE < 9.
You can detect this using "use strict" like this:
"use strict";
try {
myVar = 7;
console.log("myVar is "+myVar);
} catch(e) {
console.log("error");
}
Run the script and it will print "error". Then comment out the "use strict" and run it again; it will print "myVar is 7".

How can I define a global variable only if it doesn't exist in ES5 strict?

I'm writing an implementation of ES Harmony Symbol/Name in ES5. I'm going to use the name Symbol, but I want the browser to use any pre-existing Symbol it has in the case that it already exists (in future browsers). I want my code to be ES5 strict compliant and portable to other projects.
Here's one way (of many) to do what I want to in ES3/ES5 non-strict:
(function() {
// If Symbol already exists, we're done.
if(typeof Symbol != 'undefined') return;
// This becomes global because it wasn't declared with var
Symbol = function() {
// ...
};
})();
However, it's not ES5 strict compliant because Symbol is not defined explicitly.
Other ways to accomplish this would involve accessing the window object (window.Symbol = ...), but this is no good either because I don't want my code to assume its running in a browser environment.
How can this be done in ES5 strict?
The answers posted by other users led me to a similar StackOverflow question which gave me the right terms to search in Google to find my answer. The solution:
I eventually was able to solve this problem with the use of an indirect eval, described here.
Using an indirect eval, covered in detail in the article linked above, executes code in global scope, as per the ES5 spec. I have chosen to go with this approach because it conforms to the ES5 spec and it allows the code to literally be dropped anywhere, even inside another function by a package manager, and still find the global object (which the other answers provided could not do).
The solution is something along these lines:
(function() {
'use strict';
var _global = (0, eval)('this');
// If Symbol is already defined, there's nothing to do.
if(_global.Symbol) return;
_global.Symbol = function() {
// ...
};
})();
The key is to use an indirect eval to retrieve the global object (this in the context of an indirect eval).
This should work in anything which is ES5 compliant, including modern browsers and non-browser environments, as I had wanted.
Thanks for all the help everyone!
The only caveat is that it does seem a little hackish to have to use eval (that's bad enough) in this indirect way (now its worse) in order to access the global object. Should a global identifier or some other method to access the global object not be in the spec?
How about you pass in the global scope that you want Symbol to be added to?
(function(global){
if(typeof global.Symbol != 'undefined') return;
// This becomes global because it wasn't declared with var
global.Symbol = function() {
// ...
};
})(window);
this adds it to window, but could be some other scope or var.
'use strict';
var Symbol = 1; // try to comment this line and run the script again
var Symbol = (function(Symbol) {
if(typeof Symbol != 'undefined') return Symbol;
Symbol = function() {
// ...
};
return Symbol;
})(Symbol);
alert(typeof Symbol);
​
http://jsfiddle.net/f0t0n/yATJW/
'use strict';
(function(g) { // g is a global context (this passed)
if(typeof g.Array != 'undefined') {
return;
}
g.Array = function() {
// ...
};
g.Array.prototype.foo = function() {
console.log('bar');
};
})(this);
console.log(this.Array);​
http://jsfiddle.net/f0t0n/prwaP/
Why does it need to be in an anonymous function?
// assuming global context
if (typeof this.Symbol === 'undefined') {
this.Symbol = function () {
// ...
};
}
or in a function, pass this as described here
(function (t) {
if (typeof t.Symbol === 'undefined') {
t.Symbol = function () {
// ...
};
}
})(this);

What is the correct way to check if a global variable exists?

JSLint is not passing this as a valid code:
/* global someVar: false */
if (typeof someVar === "undefined") {
var someVar = "hi!";
}
What is the correct way?
/*global window */
if (window.someVar === undefined) {
window.someVar = 123456;
}
if (!window.hasOwnProperty('someVar')) {
window.someVar = 123456;
}
/**
* #param {string} nameOfVariable
*/
function globalExists(nameOfVariable) {
return nameOfVariable in window
}
It doesn't matter whether you created a global variable with var foo or window.foo — variables created with var in global context are written into window.
If you are wanting to assign a global variable only if it doesn't already exist, try:
window.someVar = window.someVar || 'hi';
or
window['someVar'] = window['someVar'] || 'hi';
try
variableName in window
or
typeof window[variableName] != 'undefined'
or
window[variableName] !== undefined
or
window.hasOwnProperty(variableName)
I think this is actually a problem with JSLint. It will issue the following error:
Unexpected 'typeof'. Compare directly with 'undefined'.
I believe this is bad advice. In JavaScript, undefined is a global variable that is, usually, undefined. But some browsers allow scripts to modify it, like this: window.undefined = 'defined'. If this is the case, comparing directly with undefined can lead to unexpected results. Fortunately, current ECMA 5 compliant browsers do not allow assignments to undefined (and will throw an exception in strict mode).
I prefer typeof someVar === "undefined", as you posted, or someVar in window as Susei suggested.
if (typeof someVar === "undefined") {
var someVar = "hi!";
}
will check if someVar (local or global) is undefined.
If you want to check for a global variable you can use
if(window['someVar'] === undefined) {
...
}
assuming this is in a browser :)
As of ES6 most of other answers, including the accepted answer, are incorrect, because global variables defined by let or const, or resulting from a class declaration, do not have corresponding properties on the global object (window in a browser, or global in node.js). Several of them—mainly the ones which use typeof—can also be fooled by global variables which exist but which are set to undefined.
The only fully general way to test to see if a global variable exists—regardless of whether it has been declared using var, let or const, created via a function or class declaration, created by assignment (i.e., myVar = value at the top level of a program without any declaration for myVar) or by creating a property on the global object (i.e., window.myVar = value)—is to attempt to access it via a global eval and see if TypeError is thrown.
(This builds on an idea presented by Ferran Maylinch, but with a trick to ensure that it will work properly even when encapsulated in a function.)
function globalExists(varName) {
// Calling eval by another name causes evalled code to run in a
// subscope of the global scope, rather than the local scope.
const globalEval = eval;
try {
globalEval(varName);
return true;
} catch (e) {
return false;
}
}
undeclared = undefined;
const myConst = undefined;
let myLet;
var myVar;
globalExists('undeclared') // => true
globalExists('myConst') // => true
globalExists('myLet') // => true
globalExists('myVar') // => true
globalExists('nonexistent') // => false
globalExists('globalExists') // => true - can see itself.
globalExists('varName') // => false - not fooled by own parameters.
globalExists('globalEval') // => false - not fooled by local variable.
Note that this makes use of eval, so all the usual caveats apply: you should not supply an untrusted value as the parameter, and if you must use an untrusted value you should check to make sure that varName is a valid JavaScript identifier. Doing so is out of scope for this question, but it can be done using a (rather complex) regular expression—just beware that the correct regexp depends on the version of ECMAScript you are using, whether the code is a script or (ES6) module, whether it is in an async function, etc. etc.
bfavaretto is incorrect.
Setting the global undefined to a value will not alter tests of objects against undefined. Try this in your favorite browsers JavaScript console:
var udef; var idef = 42;
alert(udef === undefined); // Alerts "true".
alert(idef === undefined); // Alerts "false".
window.undefined = 'defined';
alert(udef === undefined); // Alerts "true".
alert(idef === undefined); // Alerts "false".
This is simply due to JavaScript ignoring all and any values attempted to be set on the undefined variable.
window.undefined = 'defined';
alert(window.undefined); // Alerts "undefined".
This would be a simple way to perform the check .
But this check would fail if variableName is declared and is assigned with the boolean value: false
if(window.variableName){
}
I think the best solution is the following:
if(window.hasOwnProperty('foo')) {
console.log('Variable is not declared');
}
The following solution will not work if the variables is declared but is not assigned (var foo;).
typeof foo === 'undefined'
If you are not sure whether a global variable is defined, you can always try accessing it and see what happens.
function node_env(name) {
try {
return process.env[name];
} catch (ignore) {}
}

this.globalvar vs window.globalvar

I recently read somewhere (I am really sorry I can't provide the source) that you can use this.varname to access globals in replacement to window.varname to save 2 chars
var myVar = "global";
function myFunc() {
var myVar = "notGlobal";
alert( this.myVar ); //global
}
It seems to work, but I want to know if:
it is safe to use in old browsers
it is cross-browser compatible
it will fail under some weird circumstances
I don't think I'd do it, but it's completely cross-browser compatible if this is referring to the global object (window). Whether it is will depend on how the function in question was called (at global scope, this does indeed refer to the global object), and whether the code in question is in "strict mode" or not. (In strict mode, this does not refer to the global object. Kudos and upvotes to Esailija for pointing that out.)
In non-strict code:
So at global scope:
console.log(this === window); // true if not in strict mode
And similarly, if you have a function you call directly:
function foo() {
console.log(this === window);
}
foo(); // Logs "true"
But, in JavaScript, this is set entirely by how a function is called. So we could call foo setting this to something else:
var obj = {};
foo.call(obj); // Now it logs "false", `this` === `obj` during the call
Similarly:
var obj = {};
obj.f = foo;
obj.f(); // Also logs "false", `this` === `obj` during the call
So in conclusion, at global scope (not in any function call), yes, this is reliably pointing to the global object, and if you control how the function gets called and you call it without setting this to anything else (via call or apply, or by using it from an object property a'la obj.f above), then, again, it will reliably refer to the global object. This is covered by sections 10.4.1 (Entering Global Code) and 10.4.3 (Entering Function Code) of the specification. This is how it's been from the very beginning, I believe; certainly for the last 15 years, so you're unlikely to find a non-compliant environment.
More reading:
Mythical methods
You must remember this
It will not work in modern browsers if someone slaps "use strict" above your code as this will be undefined inside the function.
<script type="text/javascript">
"use strict";
...
function test(){
console.log(this);
}
test(); // undefined
</script>
Note that you can save much more characters just by assigning window to some variable at the top of your code and using that as it will be shortened to some one character variable by a minimizer.
(function(global){
global.foo();
global.bar();
})(window);
would be minimized to (without whitespace):
(function(a){
a.foo();
a.bar();
})(window);
Where as this would not be touched as it's a keyword.
this always has a value. And if this hasnt been overridden somehow, then it will be window where all your globals are.
It will work in all JS implementations, but beware! This is more brittle, and it won't always point to a global variable.
For instance:
var myVar = "global";
var obj = {
myVar: "property",
fn: function() { return this.myVar; }
}
console.log(obj.fn()); // "property"
This fails because in this context this is that object. But when executing a function that is NOT a property of an object, this will default to window, like your example.

javascript "use strict" and Nick's find global function

So I saw a function that was, quite frankly beautiful in its simplicity as it allowed you to find the global object ( which depending on environ at the time may NOT have been window ) while within an anonymous function; however when you throw javascripts' "use strict"; mode it crumbles, due to the evaluation of the keyword 'this' changing. There were a few ways to accomplish this?
(function () {
var win = function () {
return (function () {
return this;
}());
};
//win now points to the global object no matter where it is called.
}());
Now, if these are called within the context of "use strict" we lose the functionality described, is there any equivalent that can be done in ES5 strict mode?
For reference
(function () {
"use strict"
//code here is in strict mode
}())
Access to the Global Object (before ES5)
If you need to access the global object without hard-coding the identifier window, you can do the following from any level of nested function scope:
var global = (function () {
return this;
}());
This way you can always get the global object, because inside functions that were invoked
as functions (that is, not as constrictors with new) this should always point to
the global object.
This is actually no longer the case in ECMAScript 5 in strict mode,
so you have to adopt a different pattern when your code is in strict mode.
For example,
if you’re developing a library, you can wrap your library code in an immediate function
(discussed in Chapter 4) and then from the global scope, pass a reference to this as a
parameter to your immediate function.
Access to the Global Object (after ES5)
Commonly, the global object is passed as an argument to the immediate function so
that it’s accessible inside of the function without having to use window: this way makes
the code more interoperable in environments outside the browser:
(function (global) {
// access the global object via `global`
}(this));
“JavaScript Patterns, by Stoyan Stefanov
(O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750.”
Solution:
var global = Function('return this')();
Works in all Browsers, Engines, ES3, ES5, strict, nested scope, etc.
A slight variation will pass JSLINT:
var FN = Function, global = FN('return this')();
Discussion
See How to get the global object in JavaScript?
Here's a snippet from Perfection Kills, using global eval.
var root = (function () {
return this || (0 || eval)('this');
}());
ECMA3, ECMA5, Strict mode, etc compatible, passes JSLint.

Categories