JavaScript 中如何获取全局对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3277182/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the global object in JavaScript?
提问by CoolAJ86
I want to check in a script if a certain other module is already loaded.
如果某个其他模块已加载,我想签入脚本。
if (ModuleName) {
// extend this module
}
But if ModuleNamedoesn't exist, that throws.
但如果ModuleName不存在,那就是throw。
If I knew what the Global Objectwas I could use that.
如果我知道那Global Object是什么,我可以使用它。
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.
但是,因为我希望我的模块与浏览器和工作node,rhino等等,我不能假设window。
As I understand it, this doesn't work in ES 5 with "use strict";
据我了解,这在 ES 5 中不起作用"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.
这些情况都不会通过 JSLint。
Am I missing anything?
我错过了什么吗?
回答by CMS
Well, you can use the typeofoperator, and if the identifier doesn't exist in any place of the scope chain, it will notthrow a ReferenceError, it will just return "undefined":
好吧,您可以使用typeof运算符,如果标识符不存在于作用域链的任何位置,它不会抛出 a ReferenceError,它只会返回"undefined":
if (typeof ModuleName != 'undefined') {
//...
}
Remember also that the thisvalue on Global code, refers to the global object, meaning that if your ifstatement is on the global context, you can simply check this.ModuleName.
还要记住,this全局代码上的值是指全局对象,这意味着如果您的if语句在全局上下文中,您可以简单地检查this.ModuleName.
About the (function () { return this; }());technique, you are right, on strict mode the thisvalue will simply be undefined.
关于该(function () { return this; }());技术,您是对的,在严格模式下,该this值将简单地为undefined.
Under strict mode there are two ways to get a reference to the Global object, no matter where you are:
在严格模式下,无论您身在何处,都有两种方法可以获取对 Global 对象的引用:
Through the
Functionconstructor:var global = Function('return this')();
通过
Function构造函数:var global = Function('return this')();
Functions created with the Functionconstructor 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.
用Function构造函数创建的函数不继承调用者的严格性,只有当它们以'use strict'指令开始它们的主体时它们才是严格的,否则它们是非严格的。
This method is compatible with any ES3 implementation.
此方法与任何 ES3 实现兼容。
Through an indirect
evalcall, for example:"use strict"; var get = eval; var global = get("this");
通过间接
eval调用,例如:"use strict"; var get = eval; var global = get("this");
The above will work because in ES5, indirect calls to eval, use the global environmentas both, the variable environment and lexical environment for the eval code.
以上将起作用,因为在 ES5 中,间接调用eval, 使用全局环境作为 eval 代码的变量环境和词法环境。
See details on Entering Eval Code, Step 1.
请参阅输入评估代码,步骤 1 的详细信息。
But be aware that the last solution will not work on ES3 implementations, because an indirect call to evalon ES3 will use the variable and lexical environments of the caller as the environments for the eval code itself.
但请注意,最后一个解决方案不适用于 ES3 实现,因为对 ES3 的间接调用eval将使用调用者的变量和词法环境作为 eval 代码本身的环境。
And at last, you may find useful to detect if strict mode is supported:
最后,您可能会发现检测是否支持严格模式很有用:
var isStrictSupported = (function () { "use strict"; return !this; })();
回答by CoolAJ86
Update 2019
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:
使用当今所有的 Webpacks 和 Broccolis、Gulps 和 Grunts、TypeScripts 和 AltScripts 以及 create-react-apps 等,这是非常无用的,但是如果您只是使用普通的、旧的、VanillaJS 并且您想要制作它同构,这可能是你最好的选择:
var global
try {
global = Function('return this')();
} catch(e) {
global = window;
}
The Function constructor invocation will work even when using --use_strictin node, as the Function constructor always executes in a global non-strict scope.
即使--use_strict在节点中使用,函数构造函数调用也能工作,因为函数构造函数总是在全局非严格范围内执行。
If the Function constructor fails, it's because you're in a browser with evaldisabled by CSP headers.
如果 Function 构造函数失败,那是因为您使用的浏览器eval被 CSP 标头禁用。
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, globalThisand window, and then duck-type checking which is the global exhaustively... :-/
当然,随着 Deno 的进行(节点替换),他们也可能会禁止 Function 构造函数,在这种情况下,它会返回到枚举对象,例如global, module, exports, globalThisand window,然后是鸭子类型检查,这是彻底的全局... :-/
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
2014 年 9 月 23 日更新
This can now fail if HTTP headers in the latest browsers explicitly forbid eval.
如果最新浏览器中的 HTTP 标头明确禁止 eval,这现在可能会失败。
A workaround would be to try / catch the original solution as only browsers are known to run this type of subset of JavaScript.
一种解决方法是尝试/捕获原始解决方案,因为只有浏览器才能运行这种类型的 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
回答by Edygar de Lima Oliveira
Why just don't simply use this in a global scope as param to a wrapper function, as follows?
为什么不简单地在全局范围内使用 this 作为包装函数的参数,如下所示?
(function (global) {
'use strict';
// Code
}(this));
回答by Edygar de Lima Oliveira
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?
我认为这在犀牛、节点、浏览器和jslint(没有额外的解决方法标志)中非常好 - 这有帮助吗?我错过了什么吗?
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).
虽然我自己倾向于使用 window 对象,如果我确实需要无头测试,我可以使用 env.js (rhino) 或 Phantom (node)。
回答by Dagg Nabbit
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.
编辑 - 只需更仔细地阅读您的帖子,并查看有关 ES5 严格模式的部分。任何人都可以对此有所了解吗?只要我记得,这一直是获取全局对象的公认方式......我当然希望它不会最终被破坏。
Edit 2 - CMS' answer has more info on ES5 strict mode's treatment of this.
编辑 2 - CMS 的回答有更多关于 ES5 严格模式对this.
回答by Shaun Lebron
ECMAScript will be adding this to its standard soon: https://github.com/tc39/proposal-global
ECMAScript 将很快将此添加到其标准中: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');
};
回答by senz
This is not passing jslint: var Fn = Function, global = Fn('return this')();
这不是通过 jslint: var Fn = Function, global = Fn('return this')();
Try it yourself: http://www.jslint.com/
自己试试:http: //www.jslint.com/
this will: var Fn = Function, global = new Fn('return this')();
这会: var Fn = Function, global = new Fn('return this')();
But effectively those are same thing according to MDN:
但实际上,根据MDN,它们是相同的:
Invoking the Function constructor as a function (without using the new operator) has the same effect as invoking it as a constructor.
将 Function 构造函数作为函数调用(不使用 new 运算符)与将其作为构造函数调用具有相同的效果。
回答by Remo H. Jansen
This following solution works in:
以下解决方案适用于:
- Chrome
- Node.JS
- Firefox
- MSIE
- Web Workers
- 铬合金
- 节点JS
- 火狐
- 微信公众平台
- 网络工作者
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
您只需要将 X 更改为您想要的变量名称
回答by Lorenz Lo Sauer
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';
}
}
}
回答by Roderick Obrist
I had this problem before, I'm not happy with the solution, but it works and passes JSLint (assume browser|assume node):
我以前遇到过这个问题,我对解决方案不满意,但它可以工作并通过 JSLint(假设浏览器|假设节点):
"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
一旦你有了 GLOBAL var,你就可以进行检查,并在脚本类型的末尾
delete GLOBAL.GLOBAL;

