閉包範例與解釋 閉包是函式被建立時所在的環境,環境由任意的局域變數所組成,這些變數是由在閉包建立的時間點上存在於作用域裡的所有變數,特殊的環境變數--本來以為應該消失,可是卻依然存在的變數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function addFn() { let num = 10 function ClosureAddFn(newNum) { num = num + newNum return num } //函示內 return 函示就會變成 『閉包』 return ClosureAddFn } const useClosure = addFn() console.log(useClosure(10)) //20 console.log(useClosure(10)) //30 console.log(useClosure(10)) //40
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function addFn() { let num = 10 function ClosureAddFn(newNum) { num = num + newNum return num } //函示內 return 函示就會變成 『閉包』 return ClosureAddFn } const useClosure = addFn() console.log(useClosure(10)) //20 console.log(useClosure(10)) //30 console.log(useClosure(10)) //40 const useClosure2 = addFn() console.log(useClosure2(100)) //110 console.log(useClosure2(100)) //210
參考資料
閉包(Closure)的細節:共用與非共用變數
閉包(Closure)的細節(二):模擬私有變數
閉包(Closure)的細節(三):閉包與記憶體洩漏
閉包(Closure)的細節(四):閉包效能與prototype
共用與非共用變數 一般函式在執行完畢時,內部的區域變數會被釋放掉,但如果在執行時產生了閉包。那閉包會保留其所在巢狀函式內的變數。讓他不至於被系統釋放掉。現在有一個問題是,閉包保留下來的變數,會與其他閉包共用嗎?這其實取決於閉包產生的位置與時間點。
同一個呼叫期間內的閉包共享變數: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function closuretest(){ x=10; function changex(cx){ x=cx; } function showx(){ console.log(x) } f1= changex; f2= showx; } closuretest(); console.log(f2())//顯示10 console.log(f1(5)) console.log(f2())//顯示5
不同呼叫期間的閉包各自擁有變數 1 2 3 4 5 6 7 8 9 10 function closuretest(ox){ var x=ox; return function(){ console.log(x) } } var f1=closuretest(5); var f2=closuretest(10); console.log(f1());//顯示5 console.log(f2());//顯示10
閉包效能與prototype 閉包有效能上的影響,主要是反映在處理速度與記憶體的占用。 以下誤用的的寫法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function MyPlayer(name,race,sex) { this.name = name.toString(); this.race = race.toString(); this.sex = sex.toString(); this.getName = function() { return this.name; }; this.getRace = function() { return this.race; }; this.getSex = function() { return this.sex; }; }
不同呼叫期間的閉包各自擁有變數 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function MyPlayer(name,race,sex) { this.name = name.toString(); this.race = race.toString(); this.sex = sex.toString(); } MyPlayer.prototype.getName = function() { return this.name; }; MyPlayer.prototype.getRace = function() { return this.race; }; MyPlayer.prototype.getSex = function() { return this.sex; };
利用原型可以讓物件共享方法,這比上面有效率的多。 這範例說明了prototype與閉包的使用時機,不過嚴格來說上面兩種做法都有點不切實際,因為其實變數本身就是公開屬性了,在為其增加公開方法其實沒必要。比較常的做法是用閉包來模擬並且存取私有變數。用prototype來實作通用方法以及存取通用的私有變數。