// 案例 A,宣告在 function 裡 functiontest() { var a = 1; console.log(a); } test(); // 1 console.log(a); // 這邊找不到 a,因此噴 Uncaught ReferenceError: a is not defined
// 案例 B,寫在 function 裡但不宣告,會自動被宣告成全域變數 functiontest() { a = 1; console.log(a); } test(); // 1 console.log(a); // 1
// 案例 B 運作方式有點類似以下寫法 var a; functiontest() { a = 1; console.log(a); } test(); // 1 console.log(a); // 1
// 案例 C,宣告在 function 外面成為全域變數 var a = 1; functiontest() { console.log(a); // 這個 function 裡找不到,於是往外找 } test(); // 1 console.log(a); // 1
// 案例 D,宣告全域變數後,在 function 內又重新賦值 var a = 20; functiontest() { a = 10; // a 重新賦值成 10 console.log(a); } test(); // 10 console.log(a); // 因此這裡也會是 10
// 案例 E,宣告全域變數後在 function 內又宣告另一個變數 a var a = 2; functiontest() { var a = 1; // 宣告在 function 內的 a 只存在這個 function 裡,不會重新賦值更動到外面的 a console.log(a); } test(); // 1 console.log(a); // 因此值還是 2
// 案例 F,不用 function 改用 if var a = 1; if (true) { var a = 2; } console.log(a); // 2
像案例 C 這樣從 test scope 找 a 變數,找不到往外找找到 global scope 的方式,被稱為 scope chain(範圍鍊)。
向案例 F 這樣不使用 function,而是使用條件式時,還記得之前說過 var 除了使用 function 時才有作用域的區別,因為這樣改到 global 原先值的情況,被稱為 ==變數汙染==。
但要特別注意以下情況:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
var a = "global"; // 全域變數
functionchange() { var a = "change"; functioninner() { var a = "inner"; test(); } inner(); }
functiontest() { // a 在 test scope 找不到於是往外找 -> global scope console.log(a); }
change(); // global
以上很容易會以為印出來的值是 'inner',不過其實跟函式在哪裡呼叫沒有關係,在設計該 function 時就已經決定好了該變數的 scope chain。不過如果改成以下,把最終的 function 放入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var a = "global"; // 全域變數
functionchange() { var a = "change"; functioninner() { var a = "inner"; functiontest() { console.log(a); } test(); } inner(); }
change(); // inner // 因為 test scope 裡面沒有 a ,因此往外找到 inner scope,inner scope a = 'inner'
評論