iT邦幫忙

DAY 10
2

Front to Back, Node.js系列 第 10

JavaScript function 延伸 closure 概念 - Node.js Day 10

前面稍微講了一下 JavaScript function 的宣告以及使用,今天將會介紹 closure 的概念在其中,讓大家了解 JavaScript 的 var 對於多重 function 的狀態,有什麼影響。
function 延伸 closure 概念 - Node.js Day 10

前面稍微講了一下 JavaScript function 的宣告以及使用,今天將會介紹 closure 的概念在其中,讓大家了解 JavaScript 的 var 對於多重 function 的狀態,有什麼影響。

內容

Closure ,對岸中文又稱為『閉包』,在原理上就是運用 JavaScript 的特性,var 的區域變數問題,在很多時候,為什麼會說 JavaScript 的 var 很重要就是在於此。

前面我們已經從各種不同變數型態,講到了 function ,這邊要結合這兩者,談談什麼叫做 closure 的概念。

先從範例開始談起,一個經典的範例就是

	var a=1;
	
	function test() {
		var a = 2;
	}
	
	test();
	
	console.log(a);
	//print: 1;

前面這個範例,因為 a 一開始宣告變數初始值為 1, 之後在 function test 裡面又另外宣告了一個 a ,這個時候的變數 a 跟外面的變數 a 分別是兩個不同的變數。

在 function 裡面 var 宣告的變數,都只會在 function 中存活著,直到 function 結束為止,所以可以看到 外部的 a變數,和 function test 裡面的 a 變數,可以視為兩個不同的變數,一個是全域變數,另外一個是只存活在 function test 的區域變數。

接著再來看看這個議題,

	var a=1;
	
	function test() {
		a = 2;
	}
	
	test();
	
	console.log(a);
	//print: 2;

前面的範例,a 變數因為是在 function 之外來宣告,因此在 test function 執行的時期,就可以觀察到 a 的數值會被改變,最後將 a 的數值印出之後 a 會從 1 變成 2。

傳遞變數 Closure

前面有提到 function 怎麼傳遞變數,這邊就不在描述這個部分,可是 closure 可以藉由參數傳遞的方式,達到許多有趣的效果,

	function test (a) {
		a += 1;
		function inner() {
			var b=2;
			return b*a;
		}
		return inner();
	}
	
	console.log(test(10));
	//print: 22;

這邊是屬於傳遞參數的另外一種 closure 的使用方法,從一開始 test function 就會從外面帶入 a 的這個變數,接著 a肯定會進行 + 1 ,比較模糊的部份是,最後會再 return inner();,這就意味著會去執行 inner(); 回傳出 inner 的結果給外部,最後才會將 inner 的回傳的結果給予最初呼叫 test function。

那再來看看另外一種變形,

	function test (a) {
	
		var r = inner(a);
		a += 1;
		function inner(a) {
			var b=2;
			return b * a;
		}
		return r;
	}
	
	console.log(test(10));
	//print: 20

上面多做了一點小小的改變,function test 的最開始,多了一個 r 的變數,會直接去執行 inner,後面才執行 a += 1,而我們最後直接回傳 r 的結果,因此就只有得到最初 a 的值 *b 的原始結果,就是我們要的數值。

延伸議題

最後來講一下 closure ,在最通用的的方式,就是直接回傳 function ,

	function test (a) {
		return function (x) {
			return x+a;
		}
	}
	
	var fn = test(10);
	console.log(fn(20));
	//print: 30

這邊可以看到 test function 裡面的架構,最後會回傳一個匿名 function,把其他雜訊 code 先刪除,看一下整體的架構,會像是,

	function test () {
		return function () {
		}
	}

一開始傳遞給予 a 的變數近來之後,會回傳給一個 function ,

	var fn = test(20);
	// fn 型態會是 function

當 fn 最後就會取得一個 function,最後一步,就是去執行 fn ,而 fn 可以帶入一個變數,這個時時候,之前帶入的 test function 中的 a 變數,會繼續保存在 inner function 裡面,所以 fn 的形態就等於 inner function ,最後取得 return 的結果。

	function (x) {
		return x+a;
	}
	
	/*
	a=10
	x=20
	a + x 
	10 + 20
	*/

最後結果就會知道是, 30

後記

Closure 在 JavaScript的程式編寫當中,是一個很重要的概念,在其他語言上比較沒有這樣的使用方式,不過在 JavaScript 中經常會使用到這樣的技巧。

尤其是在 Node.js 程式當中,許多程式的腳本都會使用到這個部分,因此建議大家可以多讀起次,多多看 Open source project ,更可以了解別人怎麼使用 closure 的概念於 JS 中。


上一篇
JavaScript 的神奇方法 function - node.js day 9
下一篇
#Function be a Class - Node.js Day 11
系列文
Front to Back, Node.js21
0
wordsmith
iT邦高手 1 級 ‧ 2012-10-18 19:06:32

就想說在Node.js party還能發文,這麼厲害 偷笑

clonn iT邦新手 3 級‧ 2012-10-18 23:55:52 檢舉

只能先出此招了!嗚嗚~

0
clonn
iT邦新手 3 級 ‧ 2012-10-22 18:33:40

將資料補強,希望大家喜歡!

我要留言

立即登入留言