zoukankan      html  css  js  c++  java
  • JavaScript 闭包

    一、JavaScript中闭包的概念:

      官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。我是感觉很晦涩,我就不在这里咬文嚼字了。

    二、闭包的解释

    在介绍闭包之前,先理解编程语言作用域的概念。js是一种脚本语言,他划分作用域的方式也很特别:只有function可以划分作用域,和C,C++,java用{}来划分作用域不同。还有,如果要在一个函数里声明一个局部变量,一定要用关键字var,否则这个变量的作用域会上升为全局。

    如:

    function foo(){

      a = 100;

      var b = 200;

      alert(a);//①100

      alert(b);//②200

    }

    alert(a);//③100

    alert(b);//④控制台报错,因为b的作用域在上述代码里只存在于foo中。出了foo函数的作用域,便被回收。

    js闭包的最简单形式:

    function foo(a){

      return function(){

        return a+1;

      }

    }

    直观的看这个闭包形式,声明一个名字为foo,形参为a的函数,foo的返回值是一个匿名函数,并且在匿名函数的内部对a进行了操作。

    如果对匿名函数不太理解,我们可以再举一个例子:

    function f1(){

      var i = 0;

      function f2(){

        alert(++i);//①f2中一定操作了 f1中的变量,闭包的效果才能体现。即,i的值可以在f1之外被引用。

      }

      return f2;//②f2一定是作为f1的返回值的。

    }

    var f3 = f1();//③用一个变量在f1外部引用f1

    f3();

    当代码执行完 var f3 = f1();之后,变量f3实际是指向了函数f2(),在执行f3()就会弹出i的值为1(第一次),然后每次执行f3(),alert弹出的值就+1。

    当函数f1内部的函数f2被函数f1外部的变量f3引用时就构成了闭包。注意①和②的条件。

    通过对js函数的执行过程的分析,我们可以深入理解和js闭包紧密相关的概念:

    函数的执行环境(excution context)、活动对象(call boject)、作用域(scope)、作用域链(scope chain)

    1、当定义函数f1的时候,js解释器会将函数f1的作用域链(scope chain)设置为定义f1时f1所在的“环境”。如果f1是一个全局函数,则scope chain中只有window对象。

    2、当执行函数f1的时候,f1会进入相应的执行环境(excution context)。

    3、当插件执行环境的过程中,首先会为f1添加一个scope属性,即f1的作用域,其值就是1步中的scope chain。即f1.scope = f1的作用域链。

    4、然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后,把活动对象添加到f1的作用域的最顶端。此时f1的作用域包含了两个对象:f1的活动对象和window对象。

    5、下一步是在活动对象上添加一个argument属性,它保存着调用函数f1时所传递的参数。

    6、最后把所有函数f1的形参和内部的函数f2的引用也添加到f1的活动对象上。在这一步中,完成了函数f2的定义,因此如同第3步,函数f2的作用域链被设置为f2被定义时所在的环境,即f1的作用域。

    至此,整个函数f1从定义到执行的步骤就完成了。此时f1返回函数f2的引用给f3,又函数f2的作用域链包含了对函数f1的活动对象的引用,也就是说f2可以访问到a中定义的所有变量和函数。函数f2被f3所引用,函数f2又依赖函数f1,因此函数f1在返回后不会被GC回收。

    了解了作用域链,便可以知道函数f2在访问一个变量的时候,搜索顺序是:

    1、先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数f1的活动对象,依次查找,直到找到为止。

    2、如果函数f2存在property原型对象,则存在查找完自身的活动对象后先查找自身的原型对象,再继续查找。

    3、如果整个作用域链上都无法找到,则返回undefined。

    注意,

      直观上,函数嵌套函数。效果上,函数外部可以访问到内部的变量或者对象。原因。。。可以理解函数嵌套时避免了垃圾回收,因为内部函数的作用,使得外部函数的生命周期变长了。

      要想深入理解,需要仔细理解一下js的执行上下文,作用域链,活动对象,变量对象。

    三、闭包的作用:

      1、模拟命名空间

      2、防止命名冲突

      3、让指定的变量常驻内存,可以模拟python包机制。

  • 相关阅读:
    Python 用SMTP发送邮件
    Python 用IMAP接收邮件
    E-mail Composition and Decoding
    用Python实现gmail邮箱服务,实现两个邮箱之间的绑定(中)
    【日志】-2013.10.31
    21本计算机数学相关的免费电子书【转】
    WordPress搭建Personal Blog【转】
    一句话点亮你的人生
    【日志】-2013.10.28
    转载-smarty教程(基本语法)
  • 原文地址:https://www.cnblogs.com/wjw-blog/p/6600073.html
Copyright © 2011-2022 走看看