如何在JavaScript中获取全局对象?

Coo*_*J86 74 javascript global

如果已加载某个其他模块,我想检查脚本.

if (ModuleName) {
    // extend this module
}
Run Code Online (Sandbox Code Playgroud)

但如果ModuleName不存在,那就是throws.

如果我知道Global Object我能用什么呢.

if (window.ModuleName) {
    // extend this module
}
Run Code Online (Sandbox Code Playgroud)

但是,因为我希望我的模块与浏览器和工作node,rhino等等,我不能假设window.

据我了解,这在ES 5中不起作用"use strict";

var MyGLOBAL = (function () {return this;}()); // MyGlobal becomes null
Run Code Online (Sandbox Code Playgroud)

这也会因抛出异常而失败

var MyGLOBAL = window || GLOBAL
Run Code Online (Sandbox Code Playgroud)

所以我似乎离开了

try {
    // Extend ModuleName
} 
catch(ignore) {
}
Run Code Online (Sandbox Code Playgroud)

这些情况都不会传递JSLint.

我错过了什么吗?

CMS*_*CMS 92

好吧,你可以使用typeof运算符,如果标识符链的任何地方都不存在标识符,它就不会抛出ReferenceError,它只会返回"undefined":

if (typeof ModuleName != 'undefined') {
  //...
}
Run Code Online (Sandbox Code Playgroud)

还要记住,this全局代码上的值是指全局对象,这意味着如果您的if语句位于全局上下文中,则只需检查即可this.ModuleName.

关于这项(function () { return this; }());技术,你是对的,在严格的模式下,this价值就是这样undefined.

在严格模式下,无论您身在何处,都有两种方法可以获取对Global对象的引用:

使用Function构造函数创建的函数不会继承调用者的严格性,只有当它们使用'use strict'指令启动它们的主体时它们才是严格的,否则它们是非严格的.

此方法与任何ES3实现兼容.

上面的方法是有效的,因为在ES5中,间接调用eval,使用全局环境作为两者,eval代码的变量环境和词法环境.

请参阅输入评估代码的详细信息,步骤1.

但请注意,最后一个解决方案不适用于ES3实现,因为对ES3的间接调用eval将使用调用者的变量和词法环境作为eval代码本身的环境.

最后,您可能会发现检测是否支持严格模式很有用:

var isStrictSupported = (function () { "use strict"; return !this; })();
Run Code Online (Sandbox Code Playgroud)

  • +1 @CMS - 我已经忘记了多少次我在这个网站上看到了你的答案.谢啦. (5认同)
  • 可悲的是,功能('返回此')不起作用.在Chrome中我得到:EvalError:拒绝将字符串评估为JavaScript,因为'unsafe-eval'不是以下内容安全策略指令中允许的脚本源:"script-src'self''unsafe-inline'". (4认同)

Coo*_*J86 23

疯狂的单线解决方案:

var global
try {
  global = Function('return this')();
} catch(e) {
  global = window;
}
Run Code Online (Sandbox Code Playgroud)

.

.

.

作品

  • 在每个环境中(我测试过)
  • 在严格的模式
  • 甚至在嵌套范围内

2014年9月23日更新

如果最新浏览器中的HTTP标头明确禁止eval,则现在可能会失败.

解决方法是尝试/捕获原始解决方案,因为只知道浏览器运行这种类型的JavaScript子集.

var global = Function('return this')() || (42, eval)('this');
Run Code Online (Sandbox Code Playgroud)

```

例:

var global;

try {
  global = Function('return this')() || (42, eval)('this');
} catch(e) {
  global = window;
}
Run Code Online (Sandbox Code Playgroud)

测试:

  • Chrome v12
  • Node.JS v0.4.9
  • Firefox v5
  • MSIE 8

为什么:

简而言之:这是一些奇怪的怪癖.请参阅下面的评论(或上面的帖子)

--use_strict eval从来都不是全球性的,而且global module在一个单独的上下文中运行exports 始终是全球性的.

在非严格模式下globalThis是当前上下文.如果没有当前上下文,则它假设全局.匿名函数没有上下文,因此在非严格模式下假设全局.

Sub Rant:

有JavaScript的一个愚蠢的不好的特性是中99.9%的时间只是混淆人们称为"逗号操作符".

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
Run Code Online (Sandbox Code Playgroud)

  • @ CoolAJ86,你的新代码也适用于ES3实现,但如果你仔细检查它,你会注意到间接的'eval`部分根本不是必需的,你只需要`var global = Function('return this ')();`,正如我所描述的那样,"使用`Function`构造函数创建的函数不会继承调用者的严格性",这意味着该函数的返回值将始终是*全局对象, - 无论执行 - .`||'运算符右侧的`eval`调用永远不会被调用,因为该函数将始终产生一个真值(全局obj). (3认同)

小智 5

为什么不仅仅在全局范围内使用它作为包装函数的参数,如下所示?

(function (global) {
    'use strict';
    // Code
}(this));
Run Code Online (Sandbox Code Playgroud)

  • 令人惊讶的是,没有人指出这并没有真正增加Szabolcs Kurdi的答案在一年前没有提供的任何内容.它没有解决那里的评论中提出的问题,即*需要*在全球范围内调用以便工作,但至少你的答案确实承认这一点. (2认同)