• JavaScript闭包


    闭包是JavaScript中的重要特性之一,大多数用过JavaScript的程序员也基本上都接触过闭包,不管是否知道或了解闭包这个概念。比如在用jQuery的时候:

    var count = 0;
    $('.btn').onclick = function(e) {
      count += 1;
    };

    闭包,维基百科的解释是:指引用了自由变量的函数。而我个人认为前端大牛johnhax的解释更加容易理解:闭包就是内部函数能访问外部的变量。

    所以,要理解闭包,只要理清楚变量作用域这个概念就差不多了。我也把对变量作用域的一些个人理解记录在了前两篇文章中,故这里就只简单说说一个函数它可以访问哪些作用域中的变量:

    1. 该函数自己内部声明的变量
    2. global作用域中的全局变量
    3. 如果该函数是内部函数,那它还可以访问其外部函数内声明的变量

    而对于第三点,就是闭包的行为了,用一个简单的例子来说明。

    function foo() {
      var i = 0;
      function bar() {
        i += 1;
        console.log(i);
      }
      return bar;
    }
    
    var test = foo();
    test(); // 1
    test(); // 2

    简单解读下这段代码:

    1. bar函数是内部函数,即定义在foo函数内部
    2. foo函数调用之后会将bar函数的引用作为返回值
    3. 全局作用域中有变量引用了bar函数,即bar函数还处于活动状态

    于是在foo函数已经被调用结束之后,其内部的i变量仍然没被销毁,而且在每次调用bar函数之后,其值是一直在递增的。

    如果用作用域链来解释,那就更加清晰明了了:

    1.代码载入全局执行环境,开始运行。

    globalScopeChain = {
      test: undefined,
      foo: [Function]
    };
    
    fooScopeChain = [globalScopeChain];

    2.调用foo函数。

    // 首先,`foo`函数的作用域链变为:
    fooScopeChain = [{
      arguments: [],
      i: 0,
      bar: [Function]
    }, {
      test: undefined,
      foo: [Function]
    }];
    // 声明了`bar`函数,并初始化其作用域链为:
    barScopeChain = [fooScopeChain];

    3.foo函数调用结束,并将test变量指向foo执行返回的bar函数的引用。

    // 此时全局作用域链变为:
    globalScopeChain = [{
      test: [Function],
      foo: [Function]
    }];

    4.第一次调用test,也就是bar函数。bar函数作用域链上有变量i,且值为0

    // 作用域上进行变量查找,找到后做增量赋值操作,所以`i = 1`
    barScopeChain = [{
      arguments: []
    }, {
      i: 0,
      bar: [Function]
    }, {
      test: undefined,
      foo: [Function]
    }];

    5.第二次调用test,与第4步相同。只是本次调用时,其作用域链上的i值已经在上一次调用后变成1了,所以增量赋值操作之后,得到结果为2

    因此,只要理解了作用域链,再来看闭包就很清晰了。不过对于闭包的解释,我仍然推荐开篇所提到的:内部函数能访问外部的变量,简单易懂。

  • 相关阅读:
    virtualbox+vagrant学习-2(command cli)-9-vagrant Plugin命令
    virtualbox+vagrant学习-2(command cli)-15-vagrant resume命令
    virtualbox+vagrant学习-2(command cli)-14-vagrant reload命令
    virtualbox+vagrant学习-2(command cli)-12-vagrant Provision命令
    virtualbox+vagrant学习-2(command cli)-11-vagrant PowerShell命令
    java设计模式之单例
    java设计模式之策略
    java设计模式之组合
    设计模式之适配器
    java设计模式之模板方法
  • 原文地址:https://www.cnblogs.com/human/p/3320355.html
Copyright © 2020-2023  润新知