1. 程式人生 > >JavaScript踩坑筆記09---閉包、回撥函式

JavaScript踩坑筆記09---閉包、回撥函式

閉包:

簡單點說,閉包就是一個倉庫,它的作用就是將我們要用的區域性變數暫時儲存起來。
舉例說明。

// 定義一個函式fn,其中有一個區域性變數num
function fn() {
	var num = 10;
}

以上例子中,我們在函式fn中定義了一個變數num,所以變數的num的作用域就侷限在函式fn內部。
那麼問題來了,如何在其他作用域下獲取該變數?
很簡單,我們只需要使用return關鍵字返回就可以了。

// 定義一個函式fn,其中有一個區域性變數num
function fn() {
	var num = 10;
	return num;
}
console.log
(fn()); // 10

可是這種方式有一個缺點,外部可以直接獲取該變數。
問題又來了,我又想獲取這個區域性變數,又希望能夠修改這個區域性變數,並且我對這個區域性變數還有一系列亂七八糟的操作,我該如何實現?
所以就有了閉包,舉例說明。

// 定義一個函式fn,其中有一個區域性變數num
var fn = function () {
	var num = 10;

	return {
		// 獲取變數
		getNum: function () {
			return num;
		},
		// 修改變數
		setNum: function (newNum) {
			num = newNum;
		}
// 還可以接著定義一些對變數num亂七八糟的操作 }; }; var aaa = fn(); aaa.setNum(100); console.log(aaa.getNum()); // 100

以上例子中,return返回了一個物件,物件裡定義了一些方法,這些方法就是我們所說的閉包,我們通過閉包,將區域性變數num暫時儲存了起來,並且外部無法直接獲取變數num。
閉包的作用就是將私有變數,封裝在一個安全的環境中,外部無法直接訪問。
但是閉包有一個很大缺點,也是閉包的優點,暫時儲存。
一般來說,一個函式被呼叫結束後,會銷燬他的執行上下文,這樣做的目的是節省資源。
但是閉包不一樣,拿上述例子來說,函式fn返回了一個物件,這個物件裡包含了兩個函式,這兩個函式分別建立了兩個作用域,而在這兩個作用域中,又引用了父級作用域的自由變數,所以,一旦銷燬函式fn的執行上下文,那麼它閉包中的引用的自由變數也會被銷燬,結果導致程式報錯。所以閉包正是通過這種方式,將變數num給暫時儲存了起來,這正是閉包的優點,同時,這也是閉包的缺點,大量的使用閉包會增加資源的消耗。
閉包一般有兩種表現形式。

  1. 閉包作為函式返回值。
  2. 閉包作為函式的引數。

上述例子正是閉包的第一種表現形式,也是常見的一種形式。第二種表現形式,我們稱之為回撥。

回撥函式:

回撥函式,顧名思義,回頭呼叫的函式,也就是說該函式是在一定的條件下呼叫的。
舉例說明。

// 定義主函式parentFunction
function parentFunction(fn) {
	console.log("主函式開始執行...");
	// 函式fn作為引數被傳入主函式,並在主函式內執行
	fn();
	console.log("主函式執行完畢...");
}

// 此時函式callbackFunction為parentFunction的回撥函式
var callbackFunction = function () {
	console.log("回撥函式開始執行...");
};

parentFunction(callbackFunction);
// 主函式開始執行...
// 回撥函式開始執行...
// 主函式執行完畢...

回撥函式作為引數,傳入主函式內,並在主函式內的某一點執行,就好比是主函式內定義了這個回撥函式,所以回撥函式的本質也是閉包。
回撥函式的實際應用:

  1. 決定權交給客戶端
  2. 與客戶端進行互動

個人學習總結,歡迎批評指正