閉包解釋非常多,這裡先透過幾個方式說明一下閉包是什麼:
這個範例用花錢的概念來說明,我們每次都會傳入不同的金額,並且把剩餘的金額存在內部作用域。
閉包就是存取內部的函式,所以直接使用 buyItem()(100)
兩個括號就是呼叫內部的函式。
function buyItem() {
var myMoney = 1000;
return function (price) { // 這裡就是一個閉包,不過目前只會使用一次
myMoney = myMoney - price;
return myMoney;
}
}
let balance = buyItem()(100); // 存取內部函式的變數
console.log(balance);
幹麻要這樣?
myMoney
此時的變數可以被內層的 function 存取myMoney
後來是私有的變數,外層無法讀取buyItem()(100)
時,等同於呼叫一次外層,在呼叫一次內層,最終將內層的值回傳給 balance
的變數。這樣還沒完,目前只是一次性運作,來調整一下程式碼。
這個的行為是直接去操作內部的錢包,就像是直接花費一樣,接下來我們會用扣款的概念,不斷的使用錢包內部的金額。
接下來不要直接呼叫,而是將函式賦予在另一個變數上,這樣的方式就會將 myMoney
這個變數存在內層的作用域,然後每次執行後不斷更新此值。
function buyItem() {
var myMoney = 1000;
return function (price) { // 這個閉包目前會被重複呼叫
myMoney = myMoney - price;
// myMoney 第一次由外部傳入,接下來在這個 function 內不斷更新
return myMoney;
}
}
var balance = buyItem(); // 存取內部函式的變數
balance(100); // 900
balance(100); // 800
balance(100); // 700
// 每次執行都是跑內層的函式,因此也只更新內層的函式變數
然後勒?
buyItem()
直接執行會出現 function ...
,所以沒辦法直接使用。buyItem()
使其可以不斷的反覆呼叫,且內層記憶體不會被釋放。myMoney
變數會不斷的被更新。小明拜訪完漂亮阿姨以後,接著遇到 Rich 的朋友 "杰倫哥",杰倫哥與小明去四處揮霍,小明也想趁此機會計算一下杰倫哥的花費狀況。透過閉包的方法,小明可以用同一個公式算出兩個人剩餘多少錢。
// 使用閉包產生兩個作用域
// 這裡的 money 代表身上帶的錢
function buyItem(money) {
var myMoney = money;
console.log(this); // 趁機偷問,此地的 this 指向誰?
return function (price) {
console.log(this); // 趁機偷問,此地的 this 指向誰?
// myMoney 第一次由外部傳入,接下來在這個 function 內不斷更新
myMoney = myMoney - price;
return myMoney;
}
}
let MingCost = buyItem(1000); // 存取內部函式的變數,這個是小明錢包內的錢
let JayCost = buyItem(10000); // 杰哥拿出的小錢
// 小明的內層作用域變數,也就是小明剩的錢
console.log(MingCost(100)); // 900
console.log(MingCost(100)); // 800
console.log(MingCost(100)); // 700
// 杰哥的內層作用域變數,這裡是杰哥剩的錢
console.log(JayCost(1000)); // 9000
console.log(JayCost(1000)); // 8000
console.log(JayCost(1000)); // 7000
以上片段建議分段執行,更能理解其中的過程:
let MingCost = buyItem(1000);
此時 buyItem
已經執行過一次,並且 myMoney
的變數已經依傳入的變數做調整。MingCost(100)
時,調整的則是傳至內層的 myMoney
變數。要了解閉包,就要多了解函式的作用域,掌握 變數
的作用域及函式的運作原理,此篇章難度就不會很高。
老師您好,
最近看到一個語法init : function (),用google搜尋發現出來有閉包的敘述,
語法如下所敘述:
定義 test等於init:function(){};
var test = {
init: function() {
}
};
jquery 再引入該程式,讓語法更簡潔
$(document).ready(function() {
test.init();
});
以上大概知道語法更簡潔,但不知道init:function()意思,去google搜尋卻發現跟閉包有關係,想請問老師是否知道這語法,謝謝!!
yuski 你好,
這是物件內的函式,跟閉包沒有關係喔,你可以視他唯一般的函式,在使用時要特別注意他的 this
即可。
ok.瞭解了.謝謝老師!