任何在函数内部定义的变量,都是私有变量,因为这些变量在函数外部是无法访问到的。但是在函数内部创建闭包,闭包通过自己的作用域链也可以访问这些变量,利用这一特点,就可以创建用于访问私有变量的公共方法。
1、定义
- 有权访问另一个函数作用域的函数
- 函数可以记住并访问其词法作用域,无论这个函数是在当前词法作用域之内还是之外执行
2、三种情况
- 函数作为返回值
- 函数作为参数传递
- 作用域中子级访问父级变量(作用域链)
3、三个特性
- 函数嵌套函数
- 函数内部可以引用外部的参数和变量
- 参数和变量不会被垃圾回收
4、优点
- 设计私有的方法和变量
- 避免全局变量的污染
5、闭包的内存销毁
销毁机制:垃圾回收机制
人为销毁:
①关闭网页,结束js运行环境
②为变量赋值为null
6、举例
function foo() {
var a = 2;
function bar(){
console.log(a);
}
return bar;
}
var test = foo(); //foo()函数返回bar函数,并赋值给test
test(); //2 其实是在执行bar()函数
注释:由于foo()返回bar函数,所以foo()执行后,内部作用域不会被回收,bar()依旧持有对该作用域的引用。而这个引用就叫闭包。
7、js闭包的经典用法
①记录函数被调用的次数,能够保证局部变量的内存不释放
function a(){
var i = 0;
return function(){
return ++i;
}
}
var c = a();
c();//1
c();//2
②正确给DOM注册事件处理函数
<body>
<input type="button" id="b1" value="1">
<input type="button" id="b2" value="2">
<input type="button" id="b3" value="3">
<input type="button" id="b4" value="4">
<script type="text/javascript">
var buttons = document.getElementsByTagName("input");
for (var i = 0; i < buttons.length; i++)
{
// 方式1:i的值一直是3
//buttons[i].onclick = function() {
// console.log(i + " was clicked.");
//}
// 方式2:从0到3,是我们要的效果
(function(i){
buttons[i].onclick = function() {
console.log(i + " was clicked.");
}
})(i);
}
</script>
</body>