闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现,接下来简单说说闭包的相关知识和如何实现闭包。
变量的作用域
要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
我们可以看到,函数内部是可以访问外部的变量的,但是外部是不能访问内部的变量的,闭包就是用来使得可以在函数外部读取函数内部变量的函数或者方法。
闭包的定义及其优缺点
闭包
是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。
闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
闭包是javascript
语言的一大特点,主要应用闭包场合主要是为了:设计私有的方法和变量。
闭包的经典问题
我们先看一个经典的的例子:
这个函数返回的每一个数组的值都是10,因为每个函数的作用域链中都保存着demo()的对象,所以他们引用的都是一个变量i,所以当demo()函数返回后,变量i的值是10,所以返回的都是10。为了解决这个问题,我们可以创建另外一个匿名函数强制让闭包的行为符合预期:
通过匿名函数我们实现了闭包,接下来说说闭包实现的几种方式。
访问函数内部变量的方法
方法一
|
|
方法二
|
|
方法三
|
|
方法四
|
|
内存泄露问题
由于IE的js对象和DOM对象使用不同的垃圾收集方法,因此闭包在IE中会导致内存泄露问题,也就是无法销毁驻留在内存中的元素。
以上代码创建了一个作为element元素事件处理的闭包,而这个闭包又创建了一个循环引用,由于匿名函数保存了一个对demo的活动对象的引用,因此就会导致无法减少element的引用数,只要匿名函数存在,element的引用至少是1,那么内存永远不会被回收,我们可以改写代码