概念:
闭包,可以简单理解为定义在一个函数内部的函数。
作用:
- 实现函数外部语句通过函数内部的函数对该函数中的局部变量进行操作。
示例:
function a() {
var b = 0;
function c() {
return b;
}
return c;
}
var e = a();
console.log(e()); //0
console.log(b); //出错
理解:
上面代码中如果试图之间在函数外部打印局部变量b 则会出错。但是我们可以通过在函数内部再定义一个内部函数的方式将该局部变量返回,并在外部函数将该内部函数返回,这样在外部我们就可以得到该函数内部的局部变量的值了。
- 绑定事件中保证每次得到想要的结果。
示例:
<body>
<form action="" method="post">
<input type="text"class="test" value="我是0号" />
<input type="text"class="test" value="我是1号" />
<input type="text"class="test" value="我是2号" />
</form>
</body>
<script type="text/javascript">
window.onload = function() {
var formInputs = document.getElementsByClassName("test");
for (var i = 0; i < formInputs.length; i++) {
formInputs[i].onclick = function() {
console.log(formInputs[i].value + ",i="+ i);
};
}
};
</script>
理解:
如果把上面三个输入框都点击一遍,运行结果如下:
Uncaught TypeError: Cannot read property'value' of undefined
输出结果出错了,这是因为当文档加载完执行上面的js时,for循环会正常执行,但是for循环里面的点击事件因为没有触发而不会执行,所以当触发点击事件的时候i的值实际上已经是3了,但是上面一共只有三个input框,所以i的值最多只能为2才能保证得到输出,因此i为3时运行结果出错。
下面将代码块
formInputs[i].onclick = function() {
console.log(formInputs[i].value + ",i="+ i);
};
更换为
(function(j) {
formInputs[j].onclick = function() {
console.log(formInputs[j].value + ",i="+ j);
};
})(i);
运行结果为:
我是0号,i=0
我是1号,i=1
我是2号,i=2
这样,我们通过把i的值都作为参数传入闭包函数中,在触发点击事件时每次i的值就是正常的了,由此就可以得到正确的输出结果。
另外一种解决思路:
如果我们只是想要得到正确的点击结果,并非一定要保证每次点击事件中i的值时正确的,那么我们可以在代码块
formInputs[i].onclick = function() {
console.log(formInputs[i].value + ",i="+ i);
};
的基础上直接将
formInputs[i].value
替换成
this.value
这样,我们可以得到如下运行结果:
我是0号,i=3
我是1号,i=3
我是2号,i=3
即可以保证点击事件的结果是正确的,但是i的值依旧是错误的。这是因为我们用到的this指向的是所在函数的拥有者,当前this的拥有者就是点击事件所绑定的某个input框本身,所以运行结果就是当前所点击的input框中的value值,这有点“指哪儿打哪儿”的意思。至于i的值,见上面的分析。
- 将该函数的局部变量一直存留在内存空间。
示例:
function a() {
var b = 0;
bAdd = function() {
b++;
console.log(b);
}
return b;
}
console.log(a()) //0
bAdd(); //1
bAdd(); //2
理解:
由上面的运行结果可知,函数a中定义的局部变量b在函数a调用完后并没有被清除掉,而是一直存留在内存中。这是因为我们在函数a中定义了一个全局变量bAdd,bAdd的值又是一个匿名闭包函数,该匿名闭包函数中有对局部变量b的操作,而我们知道全局变量会一直存留在内存中,所以全局变量的值也会一直存留在内存中,那么由于子匿名闭包函数和父函数a存在依赖关系,因而父函数a也会一直存留在内存当中,因此,便不难理解会得到如上的运行结果。