1. 什麼是閉包
(1)在介紹閉包之前,我們先重新認識一下函數的執行空間:
function fn(){
console.log("我是fn");
}
fn();
- 函數在執行的時候,會開闢一個執行空間(暫且叫它xxx);
- 那麼上面的代碼console.log(“我是fn”) 就是在xxx這個空間內執行的;
- 代碼執行完畢以後,這個xxx空間就銷燬了。
(2)閉包就是能夠讀取其他函數內部變量的函數,是JS中函數的一種高級應用。在JS中,只有函數內部的子函數才能讀取局部變量,因此可以把閉包簡單理解爲”定義在一個函數內部的函數
”。
例:
function fn() {
var b = 1;
// 閉包
function box() {
console.log(b);
}
// 返回一個函數,這個函數就是一個閉包
return box;
}
// res 就是 box 函數
var res = fn();
// 2秒以後調用res函數,還是能打印b的值,閉包能讓局部變量常駐內存
setTimeout(function() {
res();
}, 2000);
2. 閉包的特點
(1)可以讀取函數內部的變量。
變量的作用域無非就是兩種:全局變量和局部變量;
JS語言的特殊之處,就在於函數內部可以直接讀取全局變量;
另一方面,函數外部自然無法讀取函數內的局部變量。
(2)讓這些變量的值始終保存在內存中,作用域空間不銷燬,相對於局部變量來說,浪費了內存。
(3)保護私有變量。
3. 閉包的形成環境:
(1)函數的嵌套
(2)內部函數使用外部函數中的變量
(3)將內部函數返回,在外部函數的外部,接收返回值,執行(相當於執行了內部函數)
4. 閉包的應用場景
(1)函數作爲返回值。
function box() {
var n = 1;
function cox() {
n++;
return n;
}
return cox;
}
// res 就是一個閉包 ,n像是一個全局變量
var res = box();
console.log(res()); // 2
console.log(res()); // 3
(2)循環中的事件,事件處理函數中使用了循環的每次的計數器。
<body>
<div id="box"></div>
<ul class="list">
<li>link1</li>
<li>link2</li>
</ul>
</body>
<script>
var ali = document.querySelectorAll(".list li");
for(var i=0;i<ali.length;i++){
ali[index].onclick = (function(index){
return function(){
console.log(index);
}
})(i);
}
</script>
(3)給某些系統默認的回調函數,傳參。
function fn(a){
return function(){
console.log(a);
};
}
setTimeout(fn("world"), 1000);
(4)處理掉全局變量。
var f = (function(){
var a = "hello";
function fn(){
console.log(a + "world");
}
return fn;
})();
f();