闭包是什么?关于闭包,最简单的描述就是 ECMAScript 允许使用内部函数--即函数定义和函数表达式位于另一个函数的函数体内。
这句话太晦涩难懂,要深入理解闭包,我觉得要弄懂它的作用是什么才算是真正理解。我们知道,在函数内部定义的变量,其外部是无法访问的。
首先来看一个例子
function a(){ var i =0; //注意不能写成 i=0 } a(); alert(i);
发现函数执行返回了一个错误,说明函数内部的变量不能被访问
如果函数a内部有另外一个函数b,而且a执行之后返回b,b函数中又访问了a函数的变量,会出现什么情况呢
再看第二个例子
function a(){ var i=0; function b(){ i++; alert(i); } return b; } var res=a(); res(); //弹出1 res(); //弹出2
解析一下这个例子:由于res=a();实际上 res=function b(){i++;alert(i)},如果安装普通的情况,当a函数执行完毕之后,变量i应该是被销毁的,从函数执行的结果来看,弹出的数字出现了累加,可以证明这个变量实际上是没有被销毁,一直保存在内存当中的,只是没有一个“引用”去访问它。可以说,这就是闭包最典型的一个特征了,当一个函数内的变量需要去访问它的父函数的局部变量,并且父函数执行之后,返回这个子函数,那么就形成了一个闭包。
那么闭包究竟有什么意义呢,像上面那个例子,我们完全可以把变量赋值成全局变量啊,不一样可以用吗?
下面来看个例子:(封装)
var obj={ name:"Dvida", age:20, sex:"male", say:function(){alert("my name is "+this.name)} } obj.say();
在上面这个例子中,我们定义了一个对象obj,这个对象中有三个属性,他们都能分别访问。
obj.name; //Dvida
obj.say(); //my name is i have no name
原来对象就这样轻易被改写。利用闭包的特性,我们可以避免这个问题, 还是刚才这个对象,我们重新定义一下
var obj =function (){ var name="Dvida"; return { say:function(){alert("My name is "+name)}, getname:function(){return name}, setname:function(newname){name=newname} } }() obj.name; //undefined obj.getname();//Dvida obj.setname("Jack");//对象的名字被改写
匿名函数内部立即执行
匿名函数立即执行也可以看作是一个闭包,如:
(function(){ var a=document.title; var b="这是我的网站"; document.title=a+b; })()
这个匿名函数的外部没办法通过任何方式改变其内部的变量,在一些统计类工具中比较常见,如Google统计