一.什么是闭包
JS中,在函数内部可以读取函数外部的变量:
function outer(){
var localVal = 30;return localVal;}
outer();//30
但,在函数外部自然无法读取函数内的局部变量
function outerO{
var localVal = 30;}
alert(localVal);//error
这里有个需要注意的地方,函数内部声明变量的时候,一定要使用var命令。如果不用的话,实际上是声明了一个全局变量。
function outer(){
localVal = 30;return localVal;}
outer();
alert(localVal);//30
。
补充--JS中的函数定义
js中的定义,最常用的就是函数声明和函数表达式
js中的函数声明是指下面的形式:
函数表达式则是类似表达式那样来声明一个函数:
我们可以使用函数表达式创建一个函数并马上执行它,例如:
()();第一个括号里放一个无名的函数。
二.闭包的应用
使用闭包的好处
希望一个变量长期储存在内存当中;
避免全局变量的额污染;
私有成员的存在;
1.模块化代码
使用自执行的匿名函数来模拟块级作用域:
该方法经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数影响全局作用域。也可以减少如闭包这样的对内存的占用,由于匿名函数没有变量指向,执行完毕就可以立即销毁其作用域链。
例如:
实现a的累加,不会污染全局。
2.循环闭包
循环给每个li注册一个onlick事件,点击aleert序号。代码如下:
点击后会一直弹出同一个值aLi.length 而不是123。当点击之前,循环已经结束,i值为aLi.length。
利用闭包,建一个匿名函数,将每个i存在内存中,onclick函数用的时候提取出外部匿名函数的i值。代码如下:
或者:
3.封装
外部无法直接获取函数内的变量,可通过暴露的方法获取
但是这种方式会使我们在每一次创建新对象的时候都会创建一个这种方法。使用原型来创建一个这种方法,避免每个实例都创建不同的方法。在这里不做深究(一般构造函数加属性,原型加方法)。
4.关于this对象
this 对象是在运行时基于函数的执行环境绑定的(匿名函数中具有全局性)(this:当前发生事件的元素),有时候在一些闭包的情况下就有点不那么明显了。
代码1:
代码2:
javascript是动态(或者动态类型)语言,this关键字在执行的时候才能确定是谁。所以this永远指向调用者,即对‘调用对象‘者的引用。第一部分通过代码:执行代码
object.getNameFunc()之后,它返回了一个新的函数,注意这个函数对象跟object不是一个了,可以理解为全局函数;它不在是object的属性或者方法,此时调用者是window,因此输出是The Window。
第二部分,当执行函数object.getNameFunc()后返回的是:
此时的.this=this。而this指向object,所以that指向object。他是对object的引用,所以输出My Object。
总结:关于js中的this,记住谁调用,this就指向谁;要访问闭包的this,要定义个变量缓存下来。一般喜欢var.this = this。
5.闭包在IE下内存泄露问题
IE9之前,JScript对象和COM对象使用不同的垃圾收集例程,那么闭包会引起一些问题。
创建一个闭包,而后闭包有创建一个循环引用,那么该元素将无法销毁。常见的就是dom获取的元素或数组的属性(或方法)再去调用自己属性等。例如:
闭包会引用包含函数的整个活动对象,即是闭包不直接引用ele,活动对象依然会对其保存一个引用,那么设置null就可以断开保存的引用,释放内存。代码如下: