|
|
|
|
|
在本文中,我將借助5個(gè)示例,介紹 JavaScript 閉包。
在了解閉包之前,你需要了解兩個(gè)概念:
JavaScript 嵌套函數(shù)
在 JavaScript 中,一個(gè)函數(shù)也可以包含另一個(gè)函數(shù),這稱為嵌套函數(shù)。例如:
// 嵌套函數(shù)示例
// 外部函數(shù)
function greet(name) {
// 內(nèi)部函數(shù)
function displayName() {
console.log('Hi' + ' ' + name);
}
// 調(diào)用內(nèi)部函數(shù)
displayName();
}
// 調(diào)用外部函數(shù)
greet('WebKaka'); // Hi WebKaka
在上面的程序中,greet()
函數(shù)包含它內(nèi)部的函數(shù)displayName()
。
返回一個(gè)函數(shù)
在 JavaScript 中,還可以在函數(shù)中返回一個(gè)函數(shù),例如:
function greet(name) {
function displayName() {
console.log('Hi' + ' ' + name);
}
// 返回一個(gè)函數(shù)
return displayName;
}
const g1 = greet('WebKaka');
console.log(g1); // 返回函數(shù)定義
g1(); // 調(diào)用函數(shù)
輸出
displayName() {
console.log('Hi' + ' ' + name);
}
Hi WebKaka
在上面的程序中,greet()
函數(shù)返回displayName
函數(shù)定義。
在這里,返回的函數(shù)定義被分配給g1
變量。打印時(shí)g1
使用console.log(g1)
,獲得的是函數(shù)定義。
調(diào)用函數(shù),使用g1()
。
JavaScript 閉包
在 JavaScript 中,閉包提供了從內(nèi)部函數(shù)內(nèi)部對(duì)函數(shù)外部作用域的訪問,即使在外部函數(shù)關(guān)閉之后也是如此。例如:
// 外部函數(shù)
function greet() {
// 在內(nèi)部函數(shù)外定義變量
let name = 'WebKaka';
// 內(nèi)部函數(shù)
function displayName() {
// 訪問變量 name
return 'Hi' + ' ' + name;
}
return displayName;
}
const g1 = greet();
console.log(g1); // 返回函數(shù)定義
console.log(g1()); // 返回值
輸出
displayName() {
// 訪問變量 name
return 'Hi' + ' ' + name;
}
Hi WebKaka
在上面的例子中,當(dāng)greet()
函數(shù)被調(diào)用時(shí),它返回displayName
的函數(shù)定義。
這里,g1
是對(duì)displayName()
函數(shù)的引用。
當(dāng)g1()
被調(diào)用時(shí),它仍然可以訪問該greet()
函數(shù)。
當(dāng)我們運(yùn)行時(shí)console.log(g1)
,它返回函數(shù)定義。
讓我們看另一個(gè)例子:
function calculate(x) {
function multiply(y) {
return x * y;
}
return multiply;
}
const multiply3 = calculate(3);
const multiply4 = calculate(4);
console.log(multiply3); // 返回 calculate 函數(shù)定義
console.log(multiply3()); // NaN
console.log(multiply3(6)); // 18
console.log(multiply4(2)); // 8
在上面的程序中,calculate()
函數(shù)接受一個(gè)參數(shù)x
并返回函數(shù)的函數(shù)定義multiply()
。該multiply()
函數(shù)接受一個(gè)參數(shù)y
并返回x * y
。
multiply3
和multiply4
都是閉包。
該calculate()
函數(shù)被調(diào)用時(shí)傳遞參數(shù)x
,當(dāng)multiply3(6
)和multiply4(2)
被調(diào)用時(shí),該multipy()
函數(shù)可以訪問外部calculate()
函數(shù)傳遞的X
參數(shù)。
數(shù)據(jù)隱私
JavaScript 閉包有助于保護(hù)程序的數(shù)據(jù)隱私,例如:
let a = 0;
function sum() {
function increaseSum() {
// a值增加1
return a = a + 1;
}
return increaseSum;
}
const x = sum();
console.log(x()); // 1
console.log(x()); // 2
console.log(x()); // 3
a = a + 1;
console.log(a); // 4
在上面的例子中,sum()
函數(shù)返回increaseSum()
函數(shù)的函數(shù)定義。
a
變量在increaseSum()
函數(shù)內(nèi)部增加。然而,a
變量的值也可以在函數(shù)之外更改。在這種情況下,a = a + 1;
更改函數(shù)外部變量的值。
現(xiàn)在,如果你想要a
變量只能在函數(shù)內(nèi)部增加,可以使用閉包。例如:
function sum() {
let a = 0;
function increaseSum() {
// a的值增加1
return a = a + 1;
}
return increaseSum;
}
let x = sum();
let a = 5;
console.log(x()); // 1
console.log(x()); // 2
console.log(a); // 5
在上面的例子中,sum()
函數(shù)設(shè)置了變量a
為0,并返回increaseSum()
函數(shù)。
由于閉包,即使sum()
已經(jīng)執(zhí)行,increaseSum()
仍然可以訪問a
并且可以加1,a
每次都被x()
調(diào)用。
a
變量是sum()
函數(shù)私有的,這意味著一個(gè)變量只能在sum()
函數(shù)內(nèi)部訪問。
即使你聲明a
并使用它,它也不影響sum()
函數(shù)內(nèi)部的a
變量。
總結(jié)
本文通過多個(gè)示例,介紹了JavaScript閉包的概念、用法以及功能,通過本文的學(xué)習(xí),我們應(yīng)該了解了什么是閉包,以及怎樣使用閉包。
相關(guān)文章