ECMAScript 之 Var
var 從 ES5 就存在,也是 ES5 的代表 keyword,看到 var 就可以判斷為 JavaScript。
但 var 在 ES6 有了一些改變,重要性也不若以往,TC39 甚至建議完全不要使用 var,改用 let 與 const。
Verson
ECMAScript 2015
Var
宣告變數於 function 內或 function 外 (global)。
- Scope:為 execution context,分 function (function 內) 與 global (function 外),而非
{} - Auto Global:若沒
var一個變數,會自動升級成 global 變數 (ES5 ok、但 ES6 廢除) - Undefined:有
var但未指定值,就是undefined - Hoisting:無論你寫在 function 內第幾行,都會在 code 執行
前先宣告變數 - Re-declare:若重新
var一個變數,原來的值仍會存在
Scope
scope01.js
1 | function x() { |
ES5 與 ES6 都無法執行。
z 的 execution context 為 function 內,所以 function 外部抓不到 z,會在 run-time 跳出 ReferenceError。
scope02.js
1 | z = 2; |
ES5 可執行,ES6 會噴 ReferenceError。
在 ES5 允許 global variable 不使用 var 宣告變數,但 ES6 會啟動 strict mode,儘管是 global variable,也一定要使用 var。
Auto Global
auto-global.js
1 | function x() { |
ES5 可執行,ES6 會噴 ReferenceError。
y 在 ES5 會自動升級為 global 變數,還是會印出 1,但 ES6 會啟動 strict mode,y 無法升級成 global 變數,會在 run-time 跳出 ReferenceError。
Undefined
undefined01.js
1 | console.log(a); |
ES5 與 ES6 都無法執行。
Run-time ReferenceError,因為 a 沒有 var 宣告。
undefined02.js
1 | var a; |
ES5 與 ES6 都可執行。
a 只宣告但沒有給值,因此為 undefined。
ECMAScript 對於變數,沒有
預設值,也不是null,而是特有undefined有些瀏覽器為
""
Hoisting
1 | bla = 2; |
但實際執行時為
1 | var bla; |
也就是無論是 ES5 或 ES6,都會自動將 var 移到程式碼的最前面先執行。
hoisting01.js
1 | function foo() { |
實際執行時
1 | function foo() { |
無論 ES5 或 ES6,因為 var bar 會被 Hoisting 到 function 的最前面,因此為 undefined。
因為 var 會 Hoisting,導致 JavaScript 的程式碼風格與 C# 迥異:
- JavaScript 會變數宣告在 function 內一開始
- C# 會在使用才宣告變數
hoisting02.js
1 | var x = y, y = 'A'; |
實際執行為
1 | var x; |
因為 var y 會先被 Hoisting,所以 x = y 時,y 還是 undefined,因此 x 也是 undefined。
實務上建議一行只
var一個變數
Redeclaration
redeclaration01.js
1 | var x = 2; |
ES5 與 ES6 都可執行。
實際執行為
1 | var x; |
因此 var x 被 Hoisting,所以結果都是 2。
redeclaration02.js
1 | var x = 2; |
ES5 與 ES6 都可執行。
實際執行為
1 | var x; |
由於 Hoisting 機制,JavaScript 允許 re-declare。
C# 無法這樣寫,compile 就會報錯
Babel 可編譯也可執行,SonarQube 會抓出來
但實務上不建議使用 re-declare 機制
Conclusion
- 在 ES6,無論 function 內的 variable 或 global variable,一律要使用
var,否則會噴ReferenceError - JavaScript 有獨特的
undefined,只要變數沒有給定值都是undefined - 由於 JavaScript 獨特的 Hoisting 機制,導致變數宣告都集中在 function 的最前面,與 C# 不同
- 由於 Hoisting 機制,JavaScript 允許 re-declare,與 C# 不同,但 SonarQube 會抓到錯誤,且實務上不建議這樣寫
Sample Code
完整的範例可以在我的 GitHub 上找到