與C、Java等程式語言不同,JavaScript中的變數是無類型的,所有的變數定義使用的關鍵字均為var:
如果定義變數後未對該變數進行賦值,那麼該變數的值為undefined。如上面程式碼中的a、m、n三個變數的值均為undefined。
由於JS中變數是無類型的,因此完全可以對同一個變數進行不同類型的賦值,如:
除了可以對相同變數進行不同類型的賦值,JavaScript中也可以對變數重複定義;如果這麼做,則第一次之後的變數定義語句等價於賦值語句:
在ECMAScript標準的嚴格模式(strict mode)下,所有的變數定義均需使用var關鍵字。如果不使用嚴格模式,那麼當JS程式對某個未被定義過的變數進行賦值時,程式會在JS全域物件中建立一個名稱與該變數相同的屬性,也即建立一個新的全域變數。這種做法會帶來很多問題(例如,多個JS程式間產生全域變數污染等),給後期維護帶來不小的麻煩;因此在實際開發過程中,應當盡量避免使用這種做法。
變數的儲存
如果定義的變數為全域變量,同時在變數定義過程中沒有使用var關鍵字,那麼該變數會作為全域物件的屬性而存在,可以透過存取this(全域物件)的對應屬性而取得,也可以透過使用delete關鍵字將其從全域物件中刪除掉:
delete f;
delete g;
console.log(this.f);//undefined
console.log(this.g);//undefined
對於JavaScript中的每一次函數調用,JavaScript都會建立一個局部物件以儲存在該函數中定義的局部變數;如果在該函數內部還有一個嵌套定義的函數(nested function),那麼JavaScript就會在已經定義的局部物件內部再定義一個嵌套局部物件。對於一個函數,其內部有多少層的巢狀函數定義,也就有多少層的巢狀局部物件。這個局部物件稱為“函數呼叫物件”(ECMAScript 3中的“call object”,ECMAScript 5中改名為“declarative environment record”,但個人認為還是ECMAScript 3中的名稱更容易理解一些)。
與全域物件this相反,JavaScript中不提供任何方式來存取這些局部物件(函數呼叫物件)。因此,開發人員無法對這些局部物件進行操作。不過,理解這些函數呼叫物件對於理解JavaScript中的一些概念會有很大的幫助,例如變數的作用域和閉包。