2012-05-02 51 views
4

我不得不在我的項目中使用json2.js作爲瀏覽器(IE8)JSON對象不可用於將字符串解析爲JSON。全球JSON變量覆蓋

我跑過了json2.js,並對變量聲明有疑問。

A JSON global variable is declared in json2.js like

var JSON; 
if(!JSON){ 
    JSON={}; 
} 

什麼是聲明var JSON;全球JSON對象上的效果。 我希望聲明應該覆蓋任何瀏覽器(IE8/IE7)中的全局JSON對象。 但令我驚訝的是,當全局對象可用時,它並不是重寫。 只有變量定義/啓動覆蓋全局變量? 請澄清。

+0

[IE 8的'JSON'](http://caniuse.com/#search=json)設置爲*標準模式時* – Joseph

+0

但是我的Intranet網頁(帶有JSF和Richfaces)始終加載IE7模式。這是一個不同的故事。 –

回答

3

對於每個變量聲明(不初始化!)。發生以下情況(section #10.5):

8。對於每個代碼VariableDeclarationVariableDeclarationNoIn d,在原文順序做

  1. DN標識符d
  2. varAlreadyDeclared是調用env的傳球DN作爲參數 HasBinding具體方法的結果。
  3. 如果varAlreadyDeclared,然後
    1. 呼叫env的 CreateMutableBinding傳遞DNconfigurableBindings作爲參數具體方法。
    2. 呼叫env的 SetMutableBinding具體方法傳遞DN不確定,並嚴格作爲參數。

所以你看,每當遇到var x,測試與名稱x變量是否已經存在於環境中。如果是的話,它會被忽略,但如果沒有,那麼這個變量就會被聲明並用undefined進行初始化。

由於代碼在全局範圍內運行,因此它將測試JSON是否存在於全局範圍內。所以如果JSON已經存在,var JSON;只是被忽略。


關於測試/解釋這種行爲只是一些想法:

我不知道在這一點在JavaScript執行創建全局對象,但我相信所有其他的腳本進行評估之前。這意味着,JSON存在並且在之前存在值任何變量聲明,如果您包含兩個腳本(也可以是內聯,我猜測它們會在另一個之後進行評估)只能模擬。

嘗試:

// script1.js 
var foo = 'bar'; 

// script2.js 
var foo; 
if(!foo) { 
    foo = 'baz'; 
} 
alert(foo); 

// include script2.js after script1.js 

有什麼結果呢? (cheaters look here)。


無論何時您處於單個腳本文件中,無論如何都會將所有變量聲明懸掛到頂部。所以,如果你有

var foo = 'bar'; 
var foo; 
if(!foo) { 
    foo = 'baz'; 
} 

被實際執行的腳本:

var foo; 
var foo; 
foo = 'bar'; 
if(!foo) { 
    foo = 'baz'; 
} 

你無法實際測試的第二var foo;是否覆蓋第一個,因爲在這一點上它沒有價值呢。所以這不是一個很好的例子來證明上面引用的行爲。

-1

如果您在執行該代碼塊時處於全局範圍內,那麼var JSON將覆蓋全局JSON對象,使其未定義。

如果你在任何其他範圍內(如在一個函數內),那麼將不會有任何效果。

+0

通常,腳本*在全局範圍內執行。那爲什麼呢? –

+0

我的意思是:它在全局範圍內執行,如果它存在,*不*覆蓋全局'JSON'對象。爲什麼要這樣?這將是一個完全的浪費。 –

0

它可能不是你的一個選擇,但它也可以將IE8設置爲兼容模式,以獲得本地JSON對象返回:

// in your preinit page event 
Response.AddHeader("X-UA-Compatible", "IE=8"); 

另一種選擇是隻創建JSON變量如果它不存在它:

var JSON = JSON || {}; 
3

var關鍵字也確保了在封閉函數的變量或(如在這裏)中窗口,但它不初始化一個。

其實,訂單並沒有真正的影響。

看這個代碼作爲一個例子:

a = 3; 
var a; 
alert(a); 

它提醒 「3」。

因此,您顯示的代碼中的var聲明只是確保測試中不會出現錯誤,並且不會刪除現有值。

記住這一點很好,因爲javascript中的一個常見錯誤是在一個函數中有多個var聲明,並且甚至在var聲明之前被設置的值感到驚訝。例如運行此:

if (true) { 
    ​a = 3; 
} 
// lot of code, at a different level 
if (true) { 
    var a; 
    if (433/43==3) a=true; 
    if (a) alert('should not happen'); 
}; 
​ 

是的,VAR附加的功能,而不是塊...

+0

雖然這裏有點不同。在你的例子中,變量語句被*提升到頂部。所以即使你這樣寫,實際的執行順序也是'var a; a = 3;'(或者它可能是'var a; a = 3; var a;(沒有懸掛)',這也是合理的,然後它就會適合)。在這種情況下,'JSON'是環境中的一個預定義符號,在對變量聲明進行評估之前,它已經有一個值(我假設)。我不知道,我只是想指出區別。 –