簡體   English   中英

在JavaScript中定義全局對象的實現獨立版本

[英]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僅在函數的調用時間內解決,並歸結為一些簡單的規則。

  1. 如果函數被調用一些對象的屬性,則該對象將是this里面的功能
  2. 如果按原樣調用該函數,則this將是未定義的,因此在非嚴格模式下它將是全局對象
  3. 如果函數被調用.call/.apply那么this明確自己設置。

正如您所看到的,它將屬於規則#2,它將解析為undefined 而且因為沒有"use strict";

將ThisBinding設置為全局對象

編輯:我現在在RingoJS中運行了一些快速測試,他們將“全局對象”放在實際的全局對象(由標准定義)中,即ModuleScope 僅僅因為大多數js實現中的實際全局對象具有Object和String等等,如果對象下面也包含那些對象,則不會使對象成為全局對象。 您可以在RingoJS中訪問StringObject的原因是因為他們將它們放入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,所以我只需要測試globalwindow 因此我決定堅持使用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.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中使用。 然而,一旦理解了在node.js中找到global對象的復雜性,編寫邏輯來找到它應該是相當微不足道的,正如benvie指出的那樣。 我知道我沒有。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM