一、闭包的概念
百度百科:闭包是可以读取其他函数内部变量的函数。例如在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());