2011-07-31 40 views
33

在W3School有記載:沒有var關鍵字聲明變量

如果要聲明一個變量,而無需使用「VAR」,變量總是成爲全球性的。

在函數內部聲明全局變量是否有用?我可以想象在一些事件處理程序中聲明瞭一些全局變量,但是它有什麼好處?更好地使用RAM?

回答

69

全局變量是一個壞主意。只有在絕對必要時才能使用它們。沒有RAM好處或類似的東西。

w3schools正在談論的是The Horror of Implicit Globals。考慮一下這個功能:當您運行功能

function foo() { 
    var x; 

    x = 5; 
    y = 6; 
    return x + y; 
} 

,你突然,突然冒出來,有一個名爲y全局變量。這是因爲該功能分配給y,但y未在任何地方聲明。通過JavaScript中的作用域鏈的機制,這最終將成爲全局對象(您可以在瀏覽器上以window的身份訪問)上的屬性的隱式賦值。例如,假設y在任何包含範圍不申報,這是完全一樣的:

function foo() { 
    var x; 

    x = 5; 
    window.y = 6; 
    return x + window.y; 
} 

全局對象包含所有全局(更新:使用來,ES6增加了一個方法來聲明全局不會以window結尾,請參閱下面的註釋),無論是顯式還是隱式定義的。你可以想象有一個很多全球變量是由人們的代碼意外創建的。

全局對象已經非常非常混亂。除非你正在編寫一個庫或一個必須使用多個腳本文件的頁面,否則沒有理由進一步混淆全局對象。只要定義自己一個很好的範圍界定功能,並把你的符號在裏面:

(function() { 
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions; 

    function doSomething() { 
    } 

    function doSomethingElse() { 
    } 
})(); 

如果你這樣做,你可能想調用JavaScript的新strict mode,添加在第5版規格:

(function() { 
    "use strict"; 
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions; 

    function doSomething() { 
    } 

    function doSomethingElse() { 
    } 
})(); 

...其優點是(amongst other things)使foo函數隱式創建全局變量a ReferenceError


更新:ES6和全局:作爲ES6的,一種新的全球性的創建這不是全局對象的屬性:全局通過letconst,或class創建。這些新的關鍵字在全局作用域中使用時,會創建全局對象,這些全局對象不會成爲全局對象的屬性,因此無法通過瀏覽器上的window進行訪問。

+0

-1因爲您的第一句話。全局變量是一個壞主意? **總是?**不,有時他們是一個非常好的主意。這取決於你使用的是什麼。討厭這樣的普遍性陳述是不正確的;他們不屬於編程。 – Andrew

+1

@Andrew:那麼你可以給我第二*句話的功勞。當然,其餘的答案彌補了第一句話的問題? –

+0

你的第二句話恭維第一,所以不。全局變量不是一個壞主意,他們往往是一個壞主意。不僅在絕對必要時才使用它們,只要適當地使內存全局可訪問就應該使用它們。抱歉,不,「嚴格使用」不是一種典型的JavaScript理想解決方案,除非您在全球範圍內使用它來更像官方的TypeScript;否則這就是你必須不斷維護(無處不在)的黑客攻擊,以確保你不會編寫錯誤的代碼 - 相互矛盾。 – Andrew

3

全局變量的唯一用途是如果您需要全局訪問它們。在這種情況下,您應該在函數外部使用var關鍵字聲明它們,以清楚地表明您確實想創建全局變量,並且在嘗試聲明局部變量時不會忘記var

一般,因此需要儘可能少地在全球範圍內,你應該嘗試的範圍你的代碼。您在腳本中使用的全局變量越多,您可以將其與另一個腳本一起使用的機會越少。

正常情況下,函數中的變量應該是本地的,以便它們在您退出函數時消失。

+0

奇怪的是,javascript允許構造不起作用,但只會在我們輸入錯誤時造成麻煩。 – xralf

+1

@xralf:所有語言都允許可能被濫用的構造。 「當(真的);想到的時候。 –

2

有時它有用在其內部可以在以後通過參考窗口對象容易地訪問功能創建新的全球可訪問的屬性(所有全局聲明的屬性被附着到窗的對象)。

然而,因爲它通常是宣佈什麼是全局訪問它會導致一些問題,後來因爲這些屬性可以很容易地覆蓋等,其遠不如干脆值傳遞給函數作爲參數並檢索其結果。

1

主要問題是別人可能已經在使用全球名稱相同的名稱。

然後,當您更改全局值時,您將覆蓋其值。

後來,當全球下一次使用它會神祕地改變。

+2

「別人」,可能是你,但你忘了你已經在其他地方使用過這個名字了。 – QuentinUK

+0

甚至你的頁面上有一個使用'id'的元素,因爲所有這些元素都被幾乎所有瀏覽器的'window'對象佔用。 (我認爲Firefox是唯一的堅持。) –

16

副作用當忘記VAR

有隱含的全局和明確定義的人之間的一個細微的差別。 區別在於使用刪除操作符取消定義這些變量的能力:

•無法刪除使用var創建的全局變量(在程序外部創建的變量) 。

•(如果在函數內部創建不分),而VAR創建隱含的全局可 刪除。

這表明,隱含的全局在技術上是不是真正的變量,但它們的屬性的全局對象的 。屬性可以與刪除操作員,而變量被刪除 不能:

// define three globals 
var global_var = 1; 
global_novar = 2; // antipattern 
(function() { 
    global_fromfunc = 3; // antipattern 
}()); 
// attempt to delete 
delete global_var; // false 
delete global_novar; // true 
delete global_fromfunc; // true 
// test the deletion 
typeof global_var; // "number" 
typeof global_novar; // "undefined" 
typeof global_fromfunc; // "undefined" 

在ES5嚴格模式,分配給未聲明的變量(如在前面的代碼段在兩個反模式 )將拋出異常。

JavaScript的模式,由斯托揚斯特凡(O'Reilly出版)。 Copyright 2010 Yahoo !, Inc.,9780596806750.

+0

//在變量結果類型中需要稍作修改當我試圖在w3school編譯器中運行上面的變量聲明時,我得到了alert(typeof global_var); //數字警報(typeof global_novar); // number alert(typeof global_fromfunc); // undefined –

+0

有用的解釋!謝謝 :) –