JS面试题之闭包——显示函数调用次数

365 阅读2分钟

最近遇到一个有趣的面试题,需要实现一个函数,让函数第一次调用的时候打印1,第二次调用打印2,依次类推,第n次调用打印n。可以把题目理解为每次调用,显示函数的调用次数。

这个题的核心是使用闭包。首先按常规思路分析一下,如果要显示函数的调用次数,就需要一个常数去记录,每一次调用的时候让该常数+1即可。

let count = 0;
function allCount(){
    console.log(++count);
}

但此种方法显然不符合面试官的意思,只用一个函数去解决。所以问题就转化为如何在函数内部使用一个函数,并且保存一个函数的值不被GC回收(也就是实现缓存)。闭包就能解决这个问题。

闭包的概念:一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。通俗的一种闭包形式就是,一个函数内部有一个嵌套函数,并且内部的嵌套函数调用了其上层函数的变量,就形成了闭包。此时内部的变量处于调用状态,所以是不会被GC回收掉,那么就实现了我们需要的结果。

function allCount(){
    let count = 0;
    return function(){
        console.log(++count);
    }
}

类似的题目还有,实现一个函数,能够交替输出0 1同样也是使用闭包

   function print01(){
      let count = 0;
      return function(){
        if(count === 0){
          console.log(++count)
        }
        else if(count === 1){
          console.log(--count)
        }
      }
    }

    let test = print01();
    setInterval(() => {
      test()
    },1000);

闭包是一种很好的机制,可以实现函数的缓存,像React Hooks的一些钩子函数实际上就是借助了闭包的特性,理解闭包可以和v8的垃圾回收机制一起结合理解,这样能够更深刻的理解闭包。