作用域是指變數可被訪問的範圍。在 JavaScript 中,作用域主要有以下幾種:
1.全域作用域(Global Scope): 變數在整個程式中都可被訪問。
2.函數作用域(Function Scope): 變數只在函數內部可訪問,函數外部無法訪問。
3.塊級作用域(Block Scope): 使用'let'和'const'定義的變數只在其所在的塊(例如'if'、'for'等語句)中可訪問。(ES6 引入)
var globalVar = "我是全局變量";
function exampleFunction() {
// 函數作用域
var functionVar = "我是函數作用域變量";
if (true) {
// 塊級作用域 (使用 let)
let blockVar = "我是塊級作用域變量";
var functionVarInBlock = "我也是函數作用域變量";
console.log(globalVar); // 輸出: 我是全局變量
console.log(functionVar); // 輸出: 我是函數作用域變量
console.log(blockVar); // 輸出: 我是塊級作用域變量
}
console.log(functionVarInBlock); // 輸出: 我也是函數作用域變量
// console.log(blockVar); // 這行會報錯: blockVar is not defined
}
exampleFunction();
console.log(globalVar); // 輸出: 我是全局變量
// console.log(functionVar); // 這行會報錯: functionVar is not defined
** 值得注意的是,使用'var'聲明的變量'functionVarInBlock'雖然在塊內定義,但實際上是函數作用域的。
閉包是一種函數,他能夠“記住”並訪問其外部作用域的變數,即使在其外部函數已經執行完畢的情況下。這是由於 JavaScript中的函數作用域和作用域鏈的特性。
特點:
function createCounter() {
let count = 0; // 私有變量
return function() {
count++; // 訪問並修改閉包中的變量
return count;
};
}
const counter1 = createCounter();
const counter2 = createCounter();
console.log(counter1()); // 輸出: 1
console.log(counter1()); // 輸出: 2
console.log(counter2()); // 輸出: 1
console.log(counter1()); // 輸出: 3
// 模擬私有方法
function createPerson(name) {
let age = 0; // 私有變量
function growOlder() { // 私有方法
age++;
}
return {
getName: function() { return name; },
getAge: function() { return age; },
haveBirthday: function() {
growOlder();
console.log(name + " is now " + age + " years old.");
}
};
}
const person = createPerson("Alice");
person.haveBirthday(); // 輸出: Alice is now 1 years old.
person.haveBirthday(); // 輸出: Alice is now 2 years old.
console.log(person.getAge()); // 輸出: 2
// console.log(person.age); // 這行會輸出 undefined, 因為 age 是私有的
在這個例子中有三個要注意的事:
1.'createCounter'函數返回一個新的函數,這個新函數可以訪問和修改'count'變量。
2.每次調用'createCounter'都會創建一個新的閉包,有自己的'count'變量。
3.'createPerson'函數展示了如何使用閉包來創建私有變量和方法。