js闭包

我们先来看一个简单的例子:

1 function one(){
2   var a=30;
3   return function(){
4      return a;
6 } 7 } 8 var func=one(); 9 func();

显然,最后的结果为:30;

在上面的例子中,我们执行了 func=one();之后,返回的是return的匿名函数,该匿名函数任然能够访问外部的局部变量 a,这种情况就是我们所说的闭包。在一般的函数中,函数在执行完成之后,就会释放掉该函数中的局部变量,但是闭包不会,闭包会使该局部变量一直保存在内存中。

 

在一些专业的文献中对闭包的解释是:闭包是指函数或函数的引用,与一个引用环境绑定在一起,这个引用环境是一个存储该函数每个非局部变量的表。

从简单来讲,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。

闭包的作用:一是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

 

但是,我们有时会遇到这样的情况:比如说,我们想要这个函数返回所有的 i 的值:

1 function one(){
2   var a = new Array();
3   for(var i=0;i<5;i++){
4     a[i] = function(){
5       return i;
6     };
7   }
8   return a;
9 }

 表面上看,每个函数都应该返回自己的索引值,但实际上,每个函数都返回5.因为每个函数的作用域链中都保存着 one() 函数的活动对象,他们都引用的是当 one() 函数返回后的 i 的值,即为 5 。这时,我们如果想要达到预期的效果,我们可以通过穿件另一个匿名函数强制让闭包行为符合预期:

 1 function one(){
 2   var a = new Array();
 3   for(var i=0;i<5;i++){
 4     a[i] = function(num){
 5       return function(){
 6         return num;
 7       };
 8     }(i);
 9   }
10   return a;
11 } 

在修改过后的代码中,我们重新定义了一个匿名函数,而且是立即执行的匿名函数,给这个函数传入了一个参数,即每次循环的 i 的值,这时最内层返回的 num 就是每次 i 的循环的值,可以达到我们的预期。

 

总结:从上面所说到的闭包的作用“可以使变量始终保持在内存中“中可以得到,有时在比较复杂的作用域环境中,在函数被调用之后,任然无法知道后面在何时还会再用到这些环境,所以会导致空间浪费,内存泄漏,性能消耗等坏处。所以我们要合理的使用闭包。

posted @ 2017-07-31 13:52  yuequanling  阅读(110)  评论(0编辑  收藏  举报