[英]Defining an implementation independent version of the global object in 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
屬性訪問它。
因此,此代碼段適用於所有瀏覽器以及至少RingoJS和node.js,但我還沒有測試過其他CommomJS實現。 因此,我想知道當在任何其他CommonJS實現上運行時,此代碼是否不會產生正確的結果,如果是,我將如何解決它。
最終,我打算在lambda表達式中使用它來實現我的實現獨立JavaScript框架,如下所示(來自jQuery的想法):
(function (global) {
// javascript framework
})(this.global || this);
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
成為全局對象。
實現獨立版本並非易事
(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?
);
您將需要為每個環境進行功能檢測的硬編碼。
在閱讀Esailija和Raynos的答案之后,我明白了我的代碼this.global || this
this.global || this
不適用於node.js中的所有情況; 如果全局范圍內已存在名為global
的變量,則它甚至可能在瀏覽器中失敗。
Esailija指出, this.global
並不是真正的global
對象,而是指出this
是RingoJS中的global
對象; 雖然我理解他的論點,但就我的目的而言,我需要this
this.global
而不是this
。
Raynos建議我為每個CommonJS環境進行硬編碼功能檢測。 但是因為我目前只支持RingoJS和node.js,所以我只需要測試global
和window
。 因此我決定堅持使用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 || 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
用作瀏覽器( window
)中的global
對象,並作為默認的回退。
注意:我沒有提供任何用於在node.js REPL中查找global
對象的邏輯,因為我不相信我的框架將直接在REPL中使用。 然而,一旦理解了在node.js中找到global
對象的復雜性,編寫邏輯來找到它應該是相當微不足道的,正如benvie指出的那樣。 我知道我沒有。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.