什么是闭包
根据MDN解释
函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包
该环境包含了这个闭包创建时作用域内的任何局部变量
也就是说,当函数创建时该函数会和创建它的作用域绑定,被创建的函数有一个对这个作用域的引用,该引用使得这个作用域不会被回收,从而实现函数访问这个作用域中的局部变量的效果。
闭包一般发生在函数里面
举例
function makeFunc() {
var name = "Mozilla";//makeFunc的一个局部变量
function displayName() {//displayName() 是内部函数
alert(name);// 使用了父函数中声明的变量
}
return displayName;// 此时displayName这个函数就是一个闭包
}
var myFunc = makeFunc();
myFunc();
以上代码会输出
“Mozilla”
displayName()函数中并没有变量name,为什么会输出一个值呢
这就是闭包的特性,根据MDN的定义我们可以知道,displayName()这个函数会和创建他的作用域绑定,也就是makeFunc()函数的作用域。makeFunc()函数的作用域包含了name变量,因此displayName()函数可以访问name变量。
闭包的作用
基本作用
闭包可以让你从内部函数访问外部函数作用域
通过前面的代码已经可以看出这一作用
衍生作用
- 通过闭包实现私有变量
function box(value){
var user = value;//定义一个局部变量
function run(){
return '运行中';
}
return{//返回一个对象,该对象中包含获取和修改box函数变量的方法
publicGo:function (){
return user+run();
},
getUser :function (){
return user;
}
};
}
通过这种方式将修改函数局部变量的方法return出去使得外部作用域只能通过这些方法对函数体内的变量进行操作,实现函数的私有变量,避免其他函数对变量的随意修改,使 其在逻辑上更加严谨。
- 实现私有作用域
function box(){
(function (){//此处产生闭包
for(var i=0;i<5;i++){
alert(i);
}
})();
// 这里可以继续使用 i 变量和上面的 i 变量没有关系
}
通过闭包可以实现私有作用域,在私有作用域中声明的变量不会影响私有作用域外部的变量,即使在私有作用域外不适用同名变量也不用担心会产生值覆盖的问题,增加容错率。
- 可以解决循环赋值函数时产生的问题
function box(){
var arr = [];
for(var i=0;i<5;i++){
arr[i] = function (){
return num
};
}
return arr;
}
如果不用闭包执行数组中的函数后返回的值都是5,达不到预期的效果
function box(){
var arr = [];
for(var i=0;i<5;i++){
arr[i] = (function (num){//此处应用闭包
return function (){
return num
}
})(i);
}
return arr;
}
采用闭包后,调用数组中的方法后会依次返回0,1,2,3,4。
利用改种方法可以实现给html元素绑定事件执行不同的操作
总结
- 闭包是函数和创建这个函数的作用域组成的,这个函数拥有这个作用域的引用,使该作用域得以保存,从而可以访问这个作用于中的局部变量
- 利用闭包可以创建一个单独的作用域,保护不想让外部修改的变量,可以实现模拟类中的私有变量
- 闭包可以解决DOM事件绑定产生的一些问题