在JavaScript中定义全局对象的实现独立版本

我试图用JavaScript来定义global对象,如下所示:

 var global = this.global || this; 

以上声明在全球范围内。 因此,在浏览器中, this指针是window对象的别名。 假设它是在当前网页上下文中执行的第一行JavaScript, global的值将始终与this指针或window对象的值相同。

在CommonJS实现中,如RingoJS和node.js, this指针指向当前的ModuleScope 。 但是,我们可以通过在ModuleScope上定义的global属性来访问global对象。 因此,我们可以通过this.global属性来访问它。

因此,这个代码片段适用于所有的浏览器,至lessRingoJS和node.js,但我没有testing其他的CommomJS实现。 因此,我想知道这个代码在其他CommonJS实现上运行时是否会产生正确的结果,如果有的话,我可以如何解决这个问题。

最后,我打算在一个lambdaexpression式中为我的实现独立的JavaScript框架使用它(如下所示)(来自jQuery的想法):

 (function (global) { // javascript framework })(this.global || this); 

this与范围无关。

 (function(){ (function(){ (function(){ (function(){ alert( this ); //global object })() }).bind({})() }).apply({}) }).call({}) 

this只能在函数的调用时间内解决,并归结为一些简单的规则。

  1. 如果该函数被称为某个对象的属性,那么该对象将在函数内部
  2. 如果这个函数被调用, this将是未定义的,所以在非严格模式下它将是全局对象
  3. 如果使用.call/.apply调用该函数,那么this是您自己明确设置的。

所以,正如你所看到的那样,它将归属于规则2,这个规则解决了undefined 。 而且由于没有"use strict";

将ThisBinding设置为全局对象

编辑:我现在已经在RingoJS中进行了一些快速testing,并且他们实际上把“全局对象”放在实际的全局对象(由标准定义)内,这是ModuleScope 。 仅仅因为大多数js实现中的实际全局对象都具有Object和String等,如果它们也包含这些对象,则不会使对象成为全局对象。 您可以访问RingoJS中的StringObject的原因是因为他们把它们放到ModuleScope原型中:

 var logs = require('ringo/logging').getLogger("h"); logs.info( Object.getPrototypeOf( this ) === this.global ); //true 

进一步certificateModuleScope是实际的全局对象:

 this.property = "value"; logs.info( property ); //"value" 

所以没有什么是从这种欺骗,它不能解决任何问题:

 function injectGlobal(){ globalProperty = "value"; // "use strict" would fix this! } injectGlobal() logs.info( globalProperty ); //"value" 

简单地说, this是指根据本文前面给出的规则已经实际的全局对象。 this.global不是标准定义的真正的全局对象,它只是一个容器。

另外,你可以在浏览器中模拟这种行为:

考虑scopehack.js

 this.global = window.global || top.global || {}; 

考虑main.html:

 <script src="scopehack.js"></script> <script> this.global.helloWorld = "helloWorld"; //"global scope" this.helloWorld = "helloWorld" //"ModuleScope" </script> <iframe src="module.html"></iframe> 

最后是一个“module”module.html:

 <script src="scopehack.js"></script> <script> with( this.global ) { //poor mans RhinoJS scope injection, doesn't work for writing console.log( helloWorld ); //"global scope" - "helloWorld" console.log( this.helloWorld ); //"ModuleScope" undefined } </script> 

哪一个是module.html和main.html中的实际全局对象? 还是this

TLDR:

 var obj = { "String": String, "Object": Object, ..... }; 

不使obj成为全局对象。

实现独立版本不是微不足道的

 (function (global) { // javascript framework })( this && this.global || // ringoJS typeof root !== "undefined" && root || // node.js typeof global !== "undefined" && global || // more node.js typeof GLOBAL !== "undefined" && GLOBAL || // more node.js typeof window !== "undefined" && window || // browsers this // either undefined or some global default? ); 

您将不得不在每个环境的function检测硬编码。

在阅读Esailija和Raynos的答案后,我明白了我的代码this.global || this this.global || this将不适用于node.js中的所有情况; 而且如果一个名为global的variables已经存在于全局范围内,它甚至可能会在浏览器中失败。

Esailija指出, this.global并不是真正的global对象,而是表示this是RingoJS中的global对象; 虽然我理解他的论点,但为了我的目的,我需要this this.global而不是this

Raynosbuild议我对每个CommonJS环境进行硬编码特征检测。 不过由于我目前只支持RingoJS和node.js,我只需要testingglobalwindow 。 因此我决定坚持使用this.global || this this.global || this

不过,正如我之前this.global || this this.global || this并不适用于node.js中的所有情况,正如我从benvie的评论中所理解的那样。 在node.js REPL中我意识到我需要this而不是this.global 。 但是, this.global || this this.global || this表示this.global 。 在node.js模块中,我需要this.global而不是this 。 但是,它表示this因为this.globalundefined 。 因此,为了解决这个问题,我终于决定使用下面的代码:

 (function (global) { // javascript framework })(typeof global !== "undefined" && global || this); 

我使用这个代码的原因是因为在node.js模块中this.globalundefined 。 因此我们必须直接使用global 。 因此,我们使用typeof global !== "undefined" && global获取RingoJS和node.js中的global对象; 我们使用this作为浏览器( window )中的global对象,并作为默认的回退。

注意:我没有提供任何逻辑来查找node.js REPL中的global对象,因为我不相信我的框架将直接在REPL中使用。 然而,正如Benvie指出的那样,一旦理解了在node.js中查找global对象的复杂性,编写逻辑来find它应该是相当简单的。 我知道我不知道