2012-03-09 55 views
20

在未知主機環境中獲得對ES5嚴格模式中的global object的處理的推薦方式在嚴格模式下在未知環境中獲取對未知環境中的全局對象的引用

ECMAScript不提供引用我意識到的全局對象的內置方法。如果是這樣,這是我正在尋找的答案。

已知環境中,全局對象通常具有自引用屬性。由於全局對象是VO全球範圍內,全局對象的屬性是全局變量,所以我們可以利用它們從任何地方得到一個處理全局對象:

  • 在Web瀏覽器,就可以使用windowself

  • 在node.js中,我們可以使用global

但是,在所有主機環境中情況並非一定如此。據我所知,Windows Script Host不提供任何方法來訪問全局對象。在WSH中獲取全局對象的建議方法似乎是在不解析對象的上下文中使用this關鍵字。例如:

var GLOBAL = (function(){return this}()); 

這種技術適用於任何主機環境中工作,而不是在嚴格模式下,因爲一個未定義this不引用strict mode全局對象:

如果這是在嚴格的評估模式代碼,那麼這個值不會被強制轉換爲對象。 null或未定義的此值不會轉換爲全局對象並且原始值不會轉換爲包裝對象。通過函數調用傳遞的值(包括使用Function.prototype.apply和Function.prototype.call調用的函數)不會強制將此值傳遞給對象(10.4.3,11.1.1,15.3.4.3,15.3。 4.4)。

正如預期的那樣,下面的代碼會導致undefined

(function(){ 
    "use strict"; 
    var GLOBAL = (function(){return this}()); 
    console.log(GLOBAL); 
}()); 

那麼,什麼是正確的方式得到一個處理全局對象在任何環境下,無論嚴格模式

順便說一句,我目前的做法是嗅探全局變量引用全局對象是這樣的:

var self, window, global = global || window || self; 

...,然後只用global。我認爲這是一個不好的解決方案,其原因很多,其中大部分都很明顯,並沒有解決WSH問題。

+1

你不能''嚴格使用'; (function(global){})(this)'? (我沒有測試這個)。 – Marshall 2012-03-10 00:50:16

+0

在Node.js中起作用,至少,@Marshall – 2012-03-10 01:17:48

+0

@DavidEllis woops,這是我選擇的平臺O_o我想我應該在我說什麼之前在別人檢查它; – Marshall 2012-03-10 01:27:19

回答

29

在ES5,您可以通過間接的eval調用從內部嚴格的模式得到全局對象的引用:

"use strict"; 
var global = (1,eval)('this'); 

看看my article;特別是在這個section on strict mode

+0

感謝您的迴應,我已閱讀您的許多文章(這是很好的方式),但我一定錯過了這一個。我想過使用'eval',但並不知道這種間接技巧(顯然,只是在函數範圍內使用''不帶間接評估'的eval')。 – 2012-03-10 15:23:20

+0

感謝您的好評:)說到eval技巧,我已經聽到了一些關於Node.js沒有遵循ES5行爲的說法,並且還有其他一些魔法在幕後發生。從來沒有機會測試它,所以你可能想要仔細檢查。但它在我嘗試過的所有瀏覽器中都能正常工作,而且它應該在理論上工作,因爲這就是ES5中的特點。 – kangax 2012-03-10 15:34:26

+0

我會在節點中測試它......如果它在節點中被破壞,我可以讓它檢查一個已經存在的'global'來解決這個問題(並且把例子中的'global'重命名爲其他東西如果從函數作用域調用,它將不會影響現有的'global')。這正是我正在尋找的,謝謝。 – 2012-03-10 15:39:52

1

在嚴格模式下,獲取對全局對象的引用的方法是在引用自身的全局對象中分配一個變量。

也就是說this means the global object when in the global context,所以解決的方法就是:

"use strict"; 
var global = global || this; 
(function() { global.hello = "world"; })(); 
console.log(hello); // Outputs 'world' as expected 

意味着你必須要污染與對自身的引用全局命名空間,但是像你說的,它應該已經被那裏。

+0

等一下,除非使用'typeof'檢查,否則不會引用'global'嗎? – 2013-02-06 17:36:46

+2

@wilmoore:不,因爲'var'語句被掛起。 'var global = global || this;'被有效地處理爲'var global; global = global ||這一點;'。如果'global'已經存在,'var global'是一個no-op,否則它會被創建爲初始值'undefined',然後在下一個語句中被覆蓋。 – 2014-08-25 09:43:50

+0

是的,當我最初發布時,我知道'var'提升,但說實話,我完全沒有把它放在這個特定的背景下。感謝您的領導:) – 2014-08-26 05:20:47

7

global code中,無論嚴格模式如何,thisBinding都設置爲全局對象。這意味着你可以將它從那裏傳遞到你的模塊IEFE:

// "use strict"; or not 
(function(global) { 
    "use strict"; 
    … 
    console.log(global); 
    … 
}(this)); 
+0

實際上,它類似於@DavidEllis的答案,但沒有污染全球範圍:-) – Bergi 2013-06-04 00:04:10

相關問題