美文网首页
十分钟带你理解JavaScript闭包

十分钟带你理解JavaScript闭包

作者: gaoshu883 | 来源:发表于2018-07-14 22:06 被阅读0次

    今天就让我们从JavaScript闭包的名称来源、本质、作用等几方面简洁明了地理清闭包的概念。

    从一个例子开始

    闭包的世界从不缺乏经典的编程实例,下面就是笔者从网友们那里摘抄下来的一个经典例子。

    function add () {
      var x = 1;
      return function () { console.log(++x); };
    }
    var num = add();
    num();  // 2
    num();  // 3
    num();  // 4
    

    我们从阅读理解的角度对上面这段代码进行分析:

    • 首先,声明一个函数add
    • 函数add返回一个匿名函数
    • 调用函数add
    • 匿名函数被返回

    先看到这里,然后我们可以有以下发现:

    • 函数add执行时,匿名函数只是被返回,却没有被执行,这说明这个匿名函数有可能等会才执行
    • 这个等会再执行的匿名函数,是定义在函数add中的

    继续阅读上面的代码:

    • 将返回的匿名函数赋值给num
    • 连续三次调用函数num
    • 函数add中的局部变量自增变化

    从中又可以有以下发现:

    • 一个在“另一个函数”add内部定义的、“另一个函数”add执行时它不会立刻执行的函数num,当它执行的时候,依旧可以访问到“另一个函数”add中定义的变量x

    我们先给出闭包定义:
    一个在函数(局部作用域)中定义的、异步执行的函数,叫做闭包。

    之所以叫“闭包”,是因为从代码上看,它被一对花括号闭合包裹在一个局部作用域(函数)中。

    其实,我们也可以把上面提到的“局部作用域”称作闭包,因为是它在“闭合包裹”。不管是哪种解释,都只是一个切入点,本文采用了第一种定义。

    闭包为什么存在

    我们刚刚从词法上分析了闭包的含义,也知道了为什么叫闭包。其中提到有关闭包一个非常重要的特点:闭包是异步执行的。Web开发主要是事件驱动编程,以浏览器环境为例,JavaScript主要用于处理与用户和浏览器的交互操作,需要编写各种不同事件的处理程序,而事件的处理程序都是异步的。JavaScript的应用环境要求这门语言能够很好的处理异步执行。即使一个异步程序定义在局部作用域下,但是只要我们可以调用到它,这个异步程序就应该不出问题的执行。为了让它执行不出错,它所处的局部作用域中的变量对象就必须一直保持在内存中,以便可以随时访问到。所以,我们可以认为:闭包,是JavaScript语言的一种机制。

    另一个经典的例子

    for (var i = 0; i < 5; ++i) {
      (function (i) {
        setTimeout(function () {
          console.log(i);
        }, 100 * i);
      }(i));
    }
    
    // 控制台依次打印出
    // 0
    // 1
    // 2
    // 3
    // 4
    

    简要分析如下:

    • i为0开始执行循环
    • 循环体是一个立刻执行函数,形成一个局部作用域0
    • 局部作用域0下的局部变量i为0
    • 局部作用域0下,有一个异步执行的匿名函数0(延迟0ms后执行)
    • 执行下一次循环,i为1
    • 一个立刻执行函数,形成一个局部作用域1
    • 局部作用域1下的局部变量i为1
    • 局部作用域1下,有一个异步执行的匿名函数1(延迟100ms后执行)
    • ......依次类推
    • 循环执行完毕后,setTimeout异步程序开始执行
    • 匿名函数0被调用,打印的值从局部作用域0中获得,即为0
    • ......依次类推
    • 从而依次打印出 0 1 2 3 4

    相关文章

      网友评论

          本文标题:十分钟带你理解JavaScript闭包

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