一、首先简述什么是闭包
为什么会有闭包这个概念,我们知道函数内部可以直接读取全局变量,但是函数外部无法读取函数内部的局部变量。为了解决这个问题,人们想出了一个办法,那就是在函数的内部,再定义一个函数。
!function(){
var n =999;
function f2(){
alert(n);
}
}()
上面的代码中,有一个局部变量n,有一个函数f2,f2里面可以访问到n变量。
像上面这样函数f2就是一个闭包,闭包就是能够读取其他函数内部变量的函数。
由于在JS语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
现在疑问来了,闭包这么简单?我听说闭包是需要函数套函数,然后return一个函数的呢!
比如这样:
(正常情况下在函数f1外部是无法获取到它内部的变量n的。由于函数里面可以访问到函数外部的变量,所以人们就想出一个办法,在f1内部再定义一个函数,然后将这个函数return出来,这样就把f1里面的变量n带出来了。)
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
这里面函数f2确实是一个闭包。
1.1、为什么要函数套函数呢?
就像一开始说的那样,本身就需要有一个局部变量,所以才把变量n放在一个函数里面,如果不把变量n放在一个函数里,n就是一个全局变量了,达不到使用闭包的目的——隐藏变量。
这也是上面为什么要放在一个立即执行函数里面。
所以函数套函数只是为了造出一个局部变量,跟闭包无关。
1.2、为什么要return f2呢?
因为如果不return,你就无法使用这个闭包。把return f2
改成window.f2 = f2
也是一样的,只要让外面可以访问到这个f2函数就行了。
所以return f2只是为了f2能被使用,也跟闭包无关。
二、闭包的作用
闭包常常用来间接访问一个变量。换句话说,隐藏一个变量。
假设我们在做一个游戏,在写其中关于还剩余几条命的代码。
如果不用闭包,你可以直接用一个全局变量:
window.lives = 30 //还有三十条命
这样看起来很不妥,我们不能让别人直接访问这个变量,那怎么办呢?
用局部变量,但是用局部变量别人又访问不到,怎么办呢?
暴露一个访问器(函数),让别人可以间接访问。
代码如下:
!function(){
var lives = 50
window.奖励一条命 = function(){
lives += 1
}
window.死一条命 = function(){
lives -= 1
}
}()
那么在其他的JS文件,就可以使用window.奖励一条命()
来涨命,使用 window.死一条命()
来让角色掉一条命。
立即执行函数里面的两个匿名函数就是闭包。可以在函数外部对函数内部的局部变量进行操作。
(完)