- Published on
面試經典題-閉包
- Authors
- Name
- Yufu
閉包
閉包是指在一個內部函數中可以訪問到其外部函數的變量或參數,即使外部函數已經返回。簡單來說,閉包是一個函數和該函數所在環境的集合。
閉包的用途
就不吊人胃口,先上code
const counterModule=()=> {
let count = 0;
const increment=()=> {
count++;
}
const decrement=()=> {
count--;
}
const getCount=()=> {
return count;
}
return {
increment: increment,
decrement: decrement,
getCount: getCount
};
}
let counter = counterModule();
counter.increment();
counter.increment();
console.log(counter.getCount()); //輸出2
counter.decrement();
console.log(counter.getCount()); //輸出1
以上例子中定義一個counterModule
函數,這個函數內定義三個私有函數increment
、decrement
和getCount
,它們都可以訪問私有變量count。
創建變量counter接counterModule
返回值,再根據需求調用模塊中的方法進行交互。
這演示了閉包最常見的基礎應用,就是私有變量的封裝,將變量封裝在函式內部,防止外部代碼訪問修改。另外,上述例子中,counterModule
內將多個函數及變量包在同一個作用域中,形成一個獨立的模塊,從而提高代碼可維護性及可重用性。
接著來看看常見的閉包題目吧!
第一題
function baseCounter() {
let count = 0;
return function () {
return count++;
};
}
let counter = baseCounter();
console.log(counter())
console.log(counter())
console.log(counter())
結果:控制台會打印 0、1、2
第二題
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
} //控制台會打印 5個 5
如果要我們用學到的閉包修改以上代碼,讓控制台打印結果為0、1、2、3、4的話,應該怎麼做呢?
結果:
for (var i = 0; i < 5; i++) {
(function(j){
setTimeout(function() {
console.log(j);
}, 1000);
})(i)
}
透過每次回圈中的i值當作參數傳遞給立即執行函式,將參數儲存在回調函數的作用域中,此時執行setTimeout時所打印的j就會是各自內部的j值
閉包可以說是非常見的面試考題,想想上次求職時閉包就被問了兩次,可見其重要性,每次面試都要讀一次閉包的相關知識,故在這邊做個紀錄,如果文章內容有誤還望讀者多多指教,今天就先到這裡~