JavaScript/閉包
外觀
閉包是一種技術,其中函式與其周圍變數(詞法環境)捆綁在一起(封裝)。 通常,閉包是在像 JavaScript 這樣的函數語言程式設計語言中實現的,它們支援柯里化。
首先,我們展示函式對其詞法環境的訪問。 僅此而已不是一個閉包。
"use strict";
function incrementByCertainValue(param) {
return param + certainValue;
}
let certainValue = 10;
alert(incrementByCertainValue(8)); // 18
certainValue = 100;
alert(incrementByCertainValue(8)); // 108
函式incrementByCertainValue將其引數增加certainValue變數的值。 因為incrementByCertainValue以及certainValue是在同一個塊內定義的,所以函式可以訪問該變數。 每當呼叫該函式時,它都會讀取該變數並使用它來計算其返回值。
為了將上面的例子擴充套件到閉包,我們必須將一個(內部)函式與訪問其詞法環境的變數(通常是另一個函式)結合起來,並且透過返回這個內部函式來儲存這種狀態。
"use strict";
function incrementByCertainValue(param) {
// declare a function that will perform the work. (Only declaration, currently not invoked.)
const add = function (certainValue) {
// access to 'param' from lexical environment and to its parameter 'certainValue'
return param + certainValue;
}
return add;
}
const incrementByFive = incrementByCertainValue(5);
alert(incrementByFive(8)); // 13
const incrementBySix = incrementByCertainValue(6);
alert(incrementBySix(8)); // 14
alert(incrementByFive(10)); // 15
(外部)函式incrementByCertainValue
- 包含一個引數
param, - 定義一個(內部)函式
add,它接受另一個引數certainValue, - 除了其引數之外,(內部)函式還可以訪問其詞法環境,其中定義了
param - 返回(內部)函式。
到目前為止,只有宣告,沒有執行程式碼。
當變數incrementByFive在第 12 行宣告時,它被初始化為函式incrementByCertainValue(5)的返回值。 這是關鍵點程式碼執行和閉包技術起作用的地方。 在incrementByCertainValue中,5 被稱為引數/變數param。 接下來,函式add使用來自其詞法環境的param建立。 此函式add接受一個引數,該引數必須稍後從呼叫例程中提供。 incrementByCertainValue的返回語句提供此函式add,該函式已將值“5”繫結到其主體中。 請注意,函式名稱add是任意的,在incrementByCertainValue之外看不到。
當incrementByCertainValue第二次使用引數“6”呼叫時,“6”將繫結到一個單獨的第二個函式。