閉包是什麼?

天下1281發表於2019-06-03

一、閉包的概念
百度百科:閉包是可以讀取其他函式內部變數的函式。例如在javascript中,只有函式內部的子函式才能讀取區域性變數,所以閉包可以理解為定義在一個函式內部的函式。在本質上,閉包是將函式外部和函式內部聯絡起來的橋樑。

在javascript第三版程式設計中是這樣定義的:閉包是有權訪問另一個函式作用域中變數的函式。
我們先看看一個簡單的例子

function test(){
	var n = 1;
	return function(){
		console.log(n);
	}
}
var result = test();
result(); //1

上面是一個簡單的閉包例子。
提問:
(1)result執行完之後,為何n變數沒有釋放???
二、閉包的應用
1.ul列表中點選每一項
html

<ul>
	<li>0</li>
	<li>1</li>
	<li>2</li>
</ul>
var oList = document.getElementsByTagName('li');
for (var i = 0; i < oList.length; i++) {
    oList[i].onclick = function () {
    	console.log(i);
	}
}

不論點選哪一個li,輸出的結果都是3。因為在點選li時,for迴圈已經遍歷完。
解決方法很多:
(1)可以記錄索引值

for (var i = 0; i < oList.length; i++) {
    oList[i].index = i;
    oList[i].onclick = function () {
        var index = this.index;
        console.log(index);
    }
}

(2)用let

for (let i = 0; i < oList.length; i++) {
   oList[i].onclick = function () {
        console.log(i);
    }
}

(3)用閉包
第一種:

function makeHelpCallback(i){
    return function(){
        console.log(i);
    }
}

for(var i=0;i<oList.length;i++){
    oList[i].onclick = makeHelpCallback(i);
}

第二種:

for (var i = 0; i < oList.length; i++) {
   (function (index) {  //index相當於形參
        oList[index].onclick = function () {
            console.log(index);
        }
    })(i) //i相當於實參
}

2.用閉包來模擬私有方法

//模組模式
var Counter = (function(){
    var privateCounter = 0;
    function changeBy(val) {
        privateCounter +=val;
    }
    return {
        increment: function(){
            changeBy(1);
        },
        decrement: function(){
            changeBy(-1);
        },
        value: function(){
            return privateCounter;
        }
    }
})()

console.log(Counter.value());
Counter.increment();
Counter.increment();
console.log(Counter.value());

Counter.decrement();
console.log(Counter.value());

相關文章