我正在尝试在一行中定义JavaScript中的global
对象,如下所示:
var global = this.global || this;
以上陈述属于全球范围。因此,在浏览器中,this
指针是window
对象的别名。假设它是在当前网页的上下文中执行的第一行JavaScript,global
的值将始终与this
指针或window
的值相同对象
在CommonJS实现中,例如RingoJS和node.js,this
指针指向当前ModuleScope
。但是,我们可以通过global
上定义的属性global
访问ModuleScope
对象。因此,我们可以通过this.global
属性访问它。
因此,此代码段适用于所有浏览器以及至少RingoJS和node.js,但我尚未测试其他CommomJS实现。因此,我想知道在任何其他CommonJS实现上运行时,此代码是否不会产生正确的结果,如果是,我可以解决它。
最终,我打算在lambda表达式中使用它来实现我的实现独立JavaScript框架,如下所示(来自jQuery的想法):
(function (global) {
// javascript framework
})(this.global || this);
答案 0 :(得分:5)
this
与范围无关。
(function(){
(function(){
(function(){
(function(){
alert( this ); //global object
})()
}).bind({})()
}).apply({})
}).call({})
this
仅在函数的调用时间内解析,并归结为一些简单的规则。
this
this
将是未定义的,因此在非严格模式下它将是全局对象.call/.apply
调用该函数,则this
由您自己明确设置。正如您所看到的,它将属于规则#2,后者将解析为undefined
。因为没有"use strict";
:
将ThisBinding设置为全局对象
编辑:我现在在RingoJS中运行了一些快速测试,他们将“全局对象”置于实际全局对象(由标准定义)ModuleScope
内。仅仅因为大多数js实现中的实际全局对象具有Object和String等等,如果对象下面也包含那些对象,则不会使对象成为全局对象。您可以在RingoJS中访问String
和Object
的原因是因为他们将它们放入ModuleScope
原型中:
var logs = require('ringo/logging').getLogger("h");
logs.info( Object.getPrototypeOf( this ) === this.global );
//true
进一步证明ModuleScope
是实际的全局对象:
this.property = "value";
logs.info( property );
//"value"
所以没有从这种诡计中获得任何东西,它没有解决任何问题:
function injectGlobal(){
globalProperty = "value"; // "use strict" would fix this!
}
injectGlobal()
logs.info( globalProperty );
//"value"
Rant over,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.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
成为全局对象。
答案 1 :(得分:2)
实施独立版本并非易事
(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?
);
您需要为每个环境进行功能检测的硬编码。
答案 2 :(得分:1)
在阅读Esailija和Raynos的回答后,我明白我的代码this.global || this
不适用于node.js中的所有情况;如果全局范围内已存在名为global
的变量,则它甚至可能在浏览器中失败。
Esailija指出this.global
并不是global
对象,而是指出this
是RingoJS中的global
对象;虽然我理解他的论点,但就我的目的而言,我需要this.global
而不是this
。
Raynos建议我为每个CommonJS环境进行硬编码功能检测。但是因为我目前只支持RingoJS和node.js,所以我只需要测试global
和window
。因此我决定坚持使用this.global || this
。
然而,正如我之前所说的那样this.global || this
对于node.js中的所有情况都不起作用,正如我从benvie的评论中所理解的那样。在node.js REPL中,我意识到我需要this
而不是this.global
。但是,this.global || this
表示this.global
。在node.js模块中,我需要this.global
而不是this
。但是,它表示this
,因为this.global
是undefined
。因此,为了解决这个问题,我最终决定使用以下代码:
(function (global) {
// javascript framework
})(typeof global !== "undefined" && global || this);
我使用此代码的原因是因为在node.js模块中this.global
是undefined
。因此,我们必须直接使用global
。因此,我们使用typeof global !== "undefined" && global
来获取RingoJS和node.js中的global
对象;我们在浏览器(this
)中使用global
作为window
对象,并作为默认回退。
注意:我没有提供任何用于在node.js REPL中查找global
对象的逻辑,因为我不相信我的框架将直接在REPL中使用无论如何。然而,一旦理解了在node.js中找到global
对象的复杂性,编写逻辑来找到它应该是相当微不足道的,正如benvie指出的那样。我知道我没有。