闭包计数器

我们需要的是这么一个变量,它在函数每次调用时不要重置,但是它存在于函数内部。
在 JavaScript 中,所有函数都能访问它们上一层的作用域!所以在父函数内定义子函数,子函数能访问父函数的变量!子函数就相当于闭包。如果这时候把计数器定义在父函数里,然后子函数调用计数器,再在父函数外面执行子函数进行计数,那么这个计数器只能通过这个嵌套函数访问到,并且每次计数都不会重置(因为我们执行的是子函数,只有执行父函数该计数器才会重置)

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();//这里var add已经是执行过后的函数了,var add=function(){..}

add();//执行匿名子函数
add(); 
add();

// 计数器为 3

----------------------------------------------------------分割线--------------------------------------------------------------

注意:要调用add函数,实现++counter,需要这样操作 :add()()。这是为什么呢?且看下图:

闭包计数器_第1张图片

如果只执行add()。那么就将按照1,2的顺序执行,最终的结果就是返回一个函数function(){return(++count)}。

所以要实现++counter,必须得对add()执行一次后的结果(就是函数function(){++count})再次调用,即调用add(),也即add()()。

但是每次调用add()(),执行的顺序就是:

1、将counter 设置为0;

2、返回一个函数 function(){++counter};

3、执行函数function(){++counter}。

每次调用都重置了counter。

结论:对于一个有闭包的函数来说,如果他有一层嵌套(即函数中嵌套一个闭包函数),那么要调用这个函数,需要两个()()。因为闭包中返回的是一个函数,调用时只用一个(),结果就是返回闭包的那个函数,而不是闭包函数的执行结果。而实际上我们需要的是执行闭包的那个函数后的结果。

再看下面这段代码:

//例2

var add = (function(){
      var counter = 0;
      return function(){
             return(++counter);
      }
})();      //这里add已经是执行过后的函数了。即add指定了函数自我调用的返回值
add();   //counter为1
add();   //counter为2
add();   //counter为3

在例2中,变量add指定的是函数自我调用的返回值(指定一个函数并立即执行该函数),即例2中的add是执行了例1中add函数后返回的结果。也就是说,add实际上就是函数function(){++function}。看下图:

闭包计数器_第2张图片

第一次调用add(),相当于执行了function(){return (++counter)}一次;

第二次调用add(),相当于又执行了function(){return (++counter)}一次;

又由于function(){return (++counter)}是闭包,引用了其父函数的变量counter,所以在函数调用完毕counter依然存在,没有清零。

而且只在第一次给add赋值时,将counter设置为0。以后每次调用add(),counter都自增一次,没有重置。也就是前文说的,父函数只执行一次,每次调用都只执行了子函数。

这是为什么呢?因为只有执行下面这个函数,counter才重置。而这个函数只在第一次给add赋值时执行过一次。以后每次调用add(),都相当于调用function(){return(++counter)}。

function(){
   var counter = 0;

   return function(){
      return (++counter);
   }
}

你可能感兴趣的:(前端)