美文网首页
5分钟入门闭包

5分钟入门闭包

作者: 佳勋学长 | 来源:发表于2017-07-14 17:14 被阅读0次

    理解闭包前先要理解两个概念:作用域和作用域链。
    一、作用域分为:

    1. 全局作用域

    2. 函数作用域

       var a = 100
       function fn() {
         var a = 200
         console.log('local: ' + a)
       }
       fn() // local: 200
       console.log('global: ' + a) // glocal: 100
      

    执行上面的代码可以看到,第一个a是定义在全局作用域里的,第二个a是定义在函数作用域里的。在全局作用域的变量a和在函数作用域变量a互不影响。
    注意:没有块级作用域。

    二、作用域链

    var a = 100
    function f1() {
      var b = 200
      function f2() {
        var c = 300
        console.log(a)
        console.log(b)
        console.log(c)
      }
      f2()
    }
    f1() // 100 200 300
    

    执行以上代码,依次打印出a, b, c的值100,200,300。其中a是定义在全局作用域里,b是定义在函数f1作用域里,c是定义在函数f2作用域里。

    当代码执行到函数f2里的console.log(a)的时候,首先会在函数f2的作用域找,没有 --> 到父级作用域即函数f1的作用域里面找,也没有 --> 再到父级作用域即全局作用域里面找,有,打印。

    同理当console.log(b)的时候首先会在函数f2的作用域找,没有 --> 到父级作用域即函数f1的作用域里面找,有,打印。

    这三个作用域组成的有序集合(f2 -- f1 -- window)就是作用域链。

    注意:函数的父级作用域指的是函数定义时候的决定的,而不是执行的时候。即函数在什么地方定义,父级作用域就在哪里。

    三、闭包
    闭包有两种应用场景:

    1. 函数作为返回值

       function fn() {
         var a = 100
         return function() {
           console.log(a)
         }
       }
       var f1 = fn()
       var a = 200
       f1() // 100
      

    fn返回一个函数,赋值给f1,执行f1()即执行fn的返回函数。返回函数在定义时的父级作用域是fn,因此返回函数里的变量a会到函数fn的作用域去找,而与函数f1执行时定义的全局作用域里的变量a无关。

    1. 函数作为参数传递

       function f1() {
         var a = 100
         return function() {
           console.log(a)
         }
       }
       var fn = f1()
       function f2(f) {
         var a = 200
         f()
       }
       f2(fn)  // 100
      

    函数f2接收一个函数作为变量传入,执行函数f即执行函数f1,剩下的代码执行过程和场景1同理。

    总结:闭包的特性让我们可以在函数作用域之外,通过作用域链访问到函数作用域内的变量,但是无法对其进行修改。

    相关文章

      网友评论

          本文标题:5分钟入门闭包

          本文链接:https://www.haomeiwen.com/subject/ksanhxtx.html