闭包对词法作用域的影响

39 阅读2分钟

先上代码

 var n = 1
      function fn() {
        var n = 2
        function f() {
          n--
          console.log(n)
        }
        f()
        //console.log(n) 可以在此处尝试调试n的值可以看出来n--影响了fn函数作用域里面的n值
        return f
      }
      var x = fn()
      x()
      console.log(n)
      //1 0 1

我们一步一步分析:

1.第一步 声明了一个x=fn(),那么此时会调用fn函数,fn内部又自己调用了一次f函数,f函数里面的n变量因为闭包特性能直接访问fn函数作用域里面的n,也就是此时fn函数里面的n2,然后进行了n--,第一次输出的结果也就是1,此时n--操作改变的其实是fn函数作用域里面的n(关键),然后我们会将函数 function f() { n-- console.log(n) }返回给x

2.第二步我们运行了x(),也就是对f进行了调用,那此时f里面的n也是访问fn里面的n值拿到的,那么上面我们说到了第一次运行n--的时候改变了nfn函数作用域里面的值,此时的n=1,当我们再次运行f里面的n--,那么调试n的值就是0

3.第三步我们直接调试了全局变量里面的n值,但是我们从始至终都没有对全局变量的n进行重新赋值,就算fn函数作用域里面有一个同名变量n,但它处于函数作用域中且用var关键词声明的(要考虑变量前面没有关键词声明的情况和var变量提升的情况),并没有影响到全局作用域里面n,我们一直都是操作的函数作用域fn里面的变量n,所以全局变量n的值调试出来是1

这个题是一个对闭包很经典的应用,创建了一个私有作用域,既能做到内部变量n的计数,又不会污染到全局变量,唯一要考虑的是内存泄漏的问题,当在合适的地方对x也就是fn()进行置空,x=null这样在一段时间后,就会触发垃圾回收机制

如果有理解不对和描述不对的地方欢迎各位大佬指正