admin管理员组文章数量:1134568
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 throw
s.
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?
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 throw
s.
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?
Share Improve this question edited Dec 18, 2013 at 7:48 Qantas 94 Heavy 16k31 gold badges72 silver badges88 bronze badges asked Jul 18, 2010 at 20:44 coolaj86coolaj86 76.9k23 gold badges116 silver badges133 bronze badges 7 | Show 2 more comments11 Answers
Reset to default 102Well, 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
.
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');
};
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).
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 don't know if this will pass JSLint but it works everywhere to get you the global object even if wrapped in a function in strict mode.
function getGlobal() {
'use strict';
try {
// Any code evaled by the Function constructor is run in global scope
var global = Function('return this')();// Works in ES3/strict mode
}
catch(e) {
// We still don't know that this is a browser environment but
// Evaled code never throws in old JS, so we know defineProperty works.
Object.defineProperty(Object.prototype, 'window', {
get: function() {
return this;// works in strict mode
},
configurable: true
});
// In modern JS, Object.prototype is in global object's prototype chain.
global = window;// returns window in browsers, global object elsewhere
delete Object.prototype.window; // Clean up Object.prototype
}
return global;
}
The above works because either browsers are too old to throw when code is eval
ed, or JS is modern enough to support Object.defineProperty
in which case either window
is the global object or Object.prototype.window
is in the prototype chain of the global object.
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';
}
}
}
本文标签: How to get the global object in JavaScriptStack Overflow
版权声明:本文标题:How to get the global object in JavaScript? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736854319a1955646.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
Fn
variable:var global = (function (fn) { return fn('return this'); }(Function));
– ahuth Commented May 23, 2013 at 12:25()
in there. – wizzwizz4 Commented Jul 17, 2016 at 12:59var global = (function(){return this}).apply(null)
. More infos at developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – mems Commented Sep 6, 2017 at 9:22