js闭包实例汇总

  Js闭包

  闭包前要了解的知识

  1. 函数作用域

  (1).Js语言特殊之处在于函数内部可以直接读取全局变量

  

复制代码 代码如下:

  <script type="text/javascript">

  var n=100;

  function parent(){

  alert(n);

  }

  parent();//100

  </script>

  如果在php里

  

复制代码 代码如下:

  <?php

  $n=100;

  function parent(){

  echo $n;

  }

  parent();//会报错 n未定义

  ?>

  (2).在函数外部无法读取函数内的局部变量

  

复制代码 代码如下:

  <script type="text/javascript">

  function parent(){

  var m=50;

  }

  parent();

  alert(m);//报错 m未定义

  </script>

  注意函数内部声明变量时一定要加var,否则就声明了一个全局变量

  

复制代码 代码如下:

  function parent(){

  m=50;

  }

  parent();

  alert(m);//50

  //当然在php里更是如此了,

  

复制代码 代码如下:

  <?php

  function parent(){

  global $m;//全局 ,定义与赋值要分开

  $m=50;

  }

  parent();

  echo $m;//50

  ?>

  //没global的话,一样会报没定义的错误

  有时,需要得到函数内部的的局部变量,就需要变通的方法实现利用js变量作用域的特点,如在函数内部定义子函数,对于子函数来说,父函数就是它的全局,子函数可以访问父函数里的变量(对于整个js代码来说又是局部变量)

  

复制代码 代码如下:

  <script type="text/javascript">

  function parent(){

  var m=50;

  function son(){

  alert(m);

  }

  return son;

  }

  var s=parent();//将结果保存在全局里

  s();//50

  </script>

  Parent内部所有局部变量对其子函数来说都是可见的,但其子函数内的局部变量对其父函数是不可见的,这就是js特有的链式作用域结构,子对象会一级一级地向上查找所有父对象的变量,父对象的所有变量对子对象都是可见的,反之不成立!上面的son函数就是闭包

  有些同学可能这样

  

复制代码 代码如下:

  function parent(){

  var m=50;

  function son(){

  alert(m);

  }

  }

  parent();

  son()//会报 函数son未定义

  注意 在javascript里,在函数里声明的函数都是局部的,函数运行完后就释放了

  注意这点与php的区别

  

复制代码 代码如下:

  <?php

  function parent(){

  function son(){

  $m=50;

  echo $m;

  }

  }

  parent();

  son();//输出50 不会报错

  ?>

  闭包

  

  函数内部定义函数,连接函数内部和外部的桥梁

  闭包的作用有2个:

  一是前面提到的读取函数内部的变量,

  二是让这些变量的值保存在内存中,实现数据共享

  下面是几个闭包的例子

  

复制代码 代码如下:

  <script type="text/javascript">

  var cnt=(function(){

  var i=0;

  return function(){

  alert(i);

  i++;

  }

  })();

  cnt();//0

  cnt();//1

  cnt();//2

  cnt();//3

  </script>

  把匿名函数的执行结果(即对里面子函数的声明赋给全局变量cut),i就保存在内存里了

  执行cut()时就直接从内存取值了,i只有cnt()函数才能调用,直接alert(i)是不行的

  还可以向闭包内传参

  

复制代码 代码如下:

  var cnt=(function(num){

  return function(){

  alert(num);

  num++;

  }

  })(5);

  cnt();//5

  cnt();//6

  cnt();//7

  //当然还可以调用时传参

  var cnt=(function(){

  var i=0;

  return function(num){

  num+=i;

  alert(num);

  i++;

  }

  })();

  cnt(1);//1

  cnt(2);//3

  cnt(3);//5

  为了对闭包有更好的理解,我们看以下代码

  比如我想返回一个数组,数组里面有5个函数,第一个函数弹出0,第二个弹出1...

  代码如果这样写

  

复制代码 代码如下:

  function box(){

  var arr=[];

  for(i=0;i<5;i++){

  arr=function(){return i;}

  }

  return arr;

  }

  var a=box();

  alert(a);//包含五个函数体的数组

  alert(a[0]());

  alert(a[1]());

  弹出的函数体

  function(){return i;}    }

  最后这个i是4,之后++成为5

  For循环停止

  发现均弹出5,明显不符合我们的要求

  解决方案1

  自我即时执行里面的函数

  

复制代码 代码如下:

  function box(){

  var arr=[];

  for(i=0;i<5;i++){

  arr=(function(num){return i;})(i);

  }

  return arr;

  }

  var a=box();

  for(var i=0;i<a.length;i++){

  alert(a);

  }

  但是我们发现 返回的数组里的元素是函数执行的结果,但我们想要的是函数有得升级我们的代码

  解决方案2

  闭包实现

  

复制代码 代码如下:

  function box(){

  var arr=[];

  for(var i=0;i<5;i++){

  arr=(function(num){

  return function(){return num;}

  })(i);

  }

  return arr;

  }

  var arr=box();

  for(var i=0;i<5;i++){

  alert(arr());//0,1,2,3,4

  }

  关键代码

  

复制代码 代码如下:

  arr=(function(num){

  return function(){return num;}

  })(i);

  i=0 时

  arr[0]=(function(num){return function(){return num;}})(0);

  1时

  arr[1]=(function(num){return function(){return num;}})(1);

  以上就是闭包的好处!非常简单实用吧。