在说 “闭包” 之前先让我们了解一下 JavaScript的作用域问题
-
词法作用域:
JavaScript 分为两种变量 :1 私有变量 2 全局变量
私有变量: 函数可以访问由函数内部定义的变量,在函数内部定义的变量为私有变量
function myFunction(){
var a=4;
return a*a ;
}
全局变量,在函数体外部定义的变量为全局变量
var a=4;
function myFunction(){
return a+a;
}
注: 变量声明时,如果不使用var关键字,那么它就是一个全局变量,即便它在函数内定义
-
嵌套函数:
嵌套函数可获取声明于外部作用域的函数:
看这段代码:
function init(){
var name="asdf";//name 是一个被init创建的局部变量
function displayName(){//displayName()是内部函数,
alert(name);//使用了父函数中声明的变量
}
displayName();
}
init();
解析: init()创建了一个局部变量name 和一个名为displayName()的函数,displayName()是定义在init()里面的内部函数
displayName()内没有自己定义的局部变量,然而它可以访问到外部函数的变量,所以子函数可以访问父函数中声明的变量name
-
闭包:
闭包的实例:
//创建闭包最常见的方式就是 函数作为返回值
function addCount(){
var count=0;
return function(){
count=count+1;
console.log(count);
};
}
解析: addCount()执行的时候,返回一个函数,函数是可以自己创建自己的作用域,但是此时返回的这个函数的内部需要引用addCount()作用域下的count变量,因此count是不会被摧毁的
-
用闭包模拟私有方法:
在很多的编程语言中,支持将方法声明为私有的,而JavaScript没有这种原生支持,但是我们可以使用闭包来模拟此方法
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, Counter.decrement 和 Counter.value
该共享环境包含两个私有项, privateCounter 和changeBy 函数
这两项都无法在这个匿名函数外部直接访问。必须通过匿名函数返回的三个公共函数访问。