js中的闭包(Closure)简例与理解(精华)

来源:互联网 发布:c语言buffer用法 编辑:程序博客网 时间:2024/06/07 06:54
wiki定义:

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法 认为闭包是由函数和与其相关的引用环境组合而成的实体。

例1:

<html><body><script type="text/javascript">function test(j) {    var i = 0;    return function() {alert("i:"+i+" ,j:"+j);        alert(j + i++);    }};test(1)();//提示1test(1)();//还是提示1test(1)();//依然提示1</script></body></html>
解释:test(1)();表示立即执行函数test(1)。

结果:依次弹出1,1,1

分析:每次i都被重置为0.


稍微改造一下:

例2:

<html><body><script type="text/javascript">function test(j) {    var i = 0;    return function() {alert("i:"+i+" ,j:"+j);        alert(j + i++);    }};var c = test(1);c();//提示1c();//提示2c();//提示3</script></body></html>

解释:c();表示立即执行test(1), 即test(1)().

结果:依次弹出1,2,3

分析:闭包是由函数和与其相关的引用环境组合而成的实体。以上js代码中,function test(j)及引用它的环境3个c()构成实体即是闭包。在闭包中变量(如此处的 i)全程共享,此处i相当于闭包中的全局变量,而不随每次c()运行而重置变量 i 为0,所以每次运行c()变量i都会累加,而每次传入的变量j不变为1。


比较分析:

例1与例2的区别:例2多了这句var c = test(1);并在后面引用,此时这个引用指向函数test();

而例1直接调用test(),例1这种用法比例2更常见,是我们平时用的最多的;

这里就用“闭包是由函数和与其相关的引用环境组合而成的实体”这句话来解释。例2中js代码中最后4行就是对test()的引用,构成函数test()的引用环境,与函数test()一起组成的实体闭包。闭包中自由变量i与函数test()一同存在。


更深入理解js解析过程:

例1中,三次直接运行test(1)()会生成三次函数的调用,函数指针指向三个不同的函数调用,这三次生成属于三个独立的个体互补影响,每次函数test()都能重新完整运行,i都能初始化为0;

但是例2中,用var c引用test()后(此时 i 离开创造它的环境test()函数),只有一份函数指针指向同一个函数调用,所以后面的虽是三次c(),但还是运行的同一个函数,因为函数中的自由变量i早在加载的时候就已经赋值为0了,放在一个属于指向这个函数test()的“暂存区”,让每次调用都共享这个变量i的值(被引用的自由变量 i 与引用它的函数test()一同存在),允许所有指向同一个函数调用的之后每次调用修改 i 的值并且会生效。所以,指向同一个函数调用的三个c()都能修改 i 的值,并且修改都生效了。

这与wiki中的定义是吻合的。

原创粉丝点击