闭包在JS中既是重点又是难点,很多JS的高级功能都会用到它。来看下面的例子: <script type="text/javascript"> //例子1: var c=998; function f1(){ var a=1; var b=2; console.log("执行函数f1"); function f2(){ console.log("执行f3"); console.log("a=",a); console.log("b=",b); console.log("c=",c); } return f2; } var res=f1(); res();分析:当执行f1时,定义了局部变量n,b, 函数f2,然后又把函数f2返回,并且用变量 res接收。整个f1函数执行完毕,正常流程应该是这个执行环境就销毁了,里面的局部变量 都销毁了,但是这里返回了函数f2,外部变量引用了f2,f2又用到了f1函数里的变量a,b 所以f1的整个执行环境都保留了下来,(这些变量的值始终保持在内存中)下次执行的时候,f2里输出a,b,它里面没有定义, 根据作用域链,它在f1里找到了变量a,b,在全局中找到了c,所以就输出了。代码中的f2就是闭包 </script> 例子2: <script type="text/javascript"> function f1(){ var n=2; nAdd=function(){ n=n+1; cosnole.log("nAdd执行了"); } function f2(){ console.log(n); } return f2; } var res=f1(); res(); //2 nAdd();//nAdd执行了 nAdd();//nAdd执行了 nAdd();//nAdd执行了 res(); //5
res实际上就是闭包f2函数。它一共运行了两次,第一次的运行后n的值变为3,第二次运行后n的值变为4。这说明,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。 为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制回收。 这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数,而这个 匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。 闭包通俗一些的理解: 当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量, 当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们. 七、Javascript的垃圾回收机制 在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。 如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。 因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。 </script>
转载请注明:副业 and 脱单研究所 » JS中的闭包二三事-1