是指在當前的 execution context 之中,變數的可訪問性accessibility 為何?(variable scope 為何?)
我們在 function A 所宣告的變數,在 function B 內部可以使用(訪問)嗎? => 不可以
function hello() {
let a = 10; // 變數a的可訪問性,只有hello()這個function才可以訪問a
console.log(a);
}
hello();
function hello2() {
console.log(a); // a是定義在hello()裡面,那hello2()可不可以去訪問變數a? => 不可以
}
hello2(); // -> ReferencrError a is not defined
另一個例子,hello2()可以訪問到的全域變數 global variable 的 x = 10 嗎? -> 可以
let x = 10; //定義在最外層的變數叫全域變數global variable
function hello() {
function hello2() { // 抓的到外層的變數值
console.log(x + 10);
}
hello2();
}
hello(); // -> 20
了解 Scope 可以知道,每個變數在哪些區域或範圍是有意義的,或者是說,變數在哪些區域是可訪問或可使用的
JavaScript 的變數有以下幾種 Scope:
Global scope
: The default scope for all code running in the script
var
、let
、const
都有 Global scope
Module scope
: The scope for code running in module mode
Function scope
: The scope is created with a function
var
、let
、const
、function declaration都有Function scope
function sayHi() {
console.log("hello");
// function declaration也有Function scope
function sayHi2() {
console.log("hello2");
}
}
sayHi2(); // -> ReferenceError sayHi2 is not defined
此外,用 let
或是 const
去宣告的變數屬於下面這個額外的 scope:(沒有var
)
Block scope
: The scope created with a pair of curly braces -> {} (a block)
會出現在兩種地方
if statement
if (true) {
let x = 10; // -> Block scope,可訪問區域只限在大括弧中
}
console.log(x); // -> ReferencrError x is not defined
loop
for (let i = 0; i < 20; i++){}
console.log(i); // -> ReferencrError i is not defined
用var是全可訪問,不會被大括弧侷限
// if statement
if (true) {
var x = 10;
}
console.log(x); // -> 10
// loop
var x = 100;
// redeclaration, reassignment
for (var x = 0; x < 10; x++){}
console.log(x); // -> 10
在函式執行環境function execution context中,如果發現不在function scope內部的變數,JavaScript 將轉到其他地方查找
閉包Closure就是指這種將函數與其周圍的狀態或語詞環境結合在一起的組合
function add(a, b){
// argument object a = 3, b = 4, c = 如果function內部找不到,就會向外找,組合起來就是Closure
return a + b + c;
}
add(3, 4); // -> 7
在 JavaScript 中,每次function execution context都會在creation phase創建closure
Closure的規則是:
let c = 100;
function add(a, b) {
let c = 5;
return a + b + c; // -> 3 + 4 + 5,先找argument object,再找local variable
}
add(3, 4); // -> 12
let myName = "Phoebe";
function sayHi() {
let myName = "Darren";
console.log(myName + "說你好"); // -> Darren說你好
sayHi2(); // -> Phoebe說你好
}
function sayHi2() {
console.log(myName + "說你好");
}
sayHi();
// -> Darren說你好
// -> Phoebe說你好
let myName = "Phoebe";
function sayHi() {
let myName = "Darren";
console.log(myName + "說你好"); // -> Darren說你好
sayHi2(); // -> Darren說你好
function sayHi2() {
console.log(myName + "說你好");
}
}
sayHi();
// -> Darren說你好
// -> Darren說你好
下一篇文章學習進階的遞迴、費波那契數列。