JavaScript闭包(closure)

闭包其实就是利用了函数作用域和匿名函数的知识,当函数A执行结束时,一部分变量变量被B引用,被引用的变量不能释放,形成了所谓的闭包。这里有篇很好的文章,可以参考一下。

下面看一个小例子:

运行上面的函数后,首先alert显示”second:3″,然后显示”第一个函数执行结束”,3秒后显示“first:3”。

仔细看一下,函数show执行结束的时候,变量n应该被释放了,内存里也就不存在了,怎么过了3秒还能显示出”first:3″呢?闭包恰恰就在此产生了,当函数show执行结束的时候,想要释放内存里的n,但发现变量n还在被一个匿名函数引用,要在3秒后调用,根据JavaScript闭包原理,内存里的n被保留了下来,于是在三秒以后仍然可以调用n。

下面看几种写法的区别:

仔细看一下上面这种写法不是闭包,只是普通的函数调用而已。

这种写法就是闭包,虽然结果是一样的,但原理不一样。

上面这种写法也是闭包,虽然结果都是一样的,但原理却不一样。这里面看到了函数也可以当作对象也传递,函数show执行后return show2,把函数show2赋值给newshow,然后3秒后,调用newshow对象,执行函数show2。

仔细比较上面3种写法,如果能悟出一些道理就好,闭包有些时候的确难理解。

稍复杂一点的例子:

上面代码中,又一次用了函数作为对象传递,n是匿名函数里的局部变量,外部是访问不到的。show是一个全局变量,应该访问不了变量n,但在函数show执行前,首先把函数匿名函数内部show2赋值给show,当后面函数show运行的时候,会调用show2的代码,而show2是可以访问n的,故结果显示为1、2、3。

另外一点值得注意的,也是很经典的一个例子。

运行后,不论点击哪一个li,都是alert提示“4”。这就是一个需要注意的地方:闭包允许内层函数引用父函数中的变量,但是该变量是最终值。闭包引用的变量i,是循环结束后的值,其实这是一个很常见的问题,解决方法也有很多。

比较常见的就是给li[i]添加属性值,比如li[i].n=i;还有就是用闭包方法解决,这个函数本身就是闭包,所谓用闭包来解决闭包的问题。代码如下:

posted @ 2015-11-04 11:08  菜菜学长  阅读(155)  评论(0编辑  收藏  举报