zoukankan      html  css  js  c++  java
  • 深入理解闭包

            这里的这个例子是引用于《JavaScript高级程序设计-第2版》的第4章-函数里的例子,结合对汤姆大叔博客里对函数的理解,需要对函数的构建及执行过程作以细致的分析理解,才能对闭包作以深入的分析与应用。以下是我对闭包的理解——

     1   (function($){
     2        
     3        function createFunction() {
     4            var result = new Array();
     5            for (var i = 0; i < 3; i++) {
     6                /**
     7                 * 当执行到下面这句代码的时候,每创建一个函数,就对应创建了一个对象,这个函数对象的[[scope]]属性里包括了该执行环境的VO和AO
     8                 * 而且这里的VO和AO充当了下面这个函数的公共作用域。
     9                 */
    10                result[i] = function() {
    11                    /**
    12                     * 1>这个函数作用域可以访问另一个函数的作用域,那必然就是闭包了
    13                     * 2>这个闭包返回了数组成员对象,会导致这里的i一直存在于内存中
    14                     * 3>这里能够引出一个公共作用域的概念:
    15                     *     a>这个函数的[[scope]] = [
    16                     *                     createFunctionContext.AO,
    17                     *                     匿名函数Context.AO,
    18                     *                     globalContext.VO
    19                     *                 ]
    20                     *    b>当去检索i变量的时候,在第一层父级执行环境createFunctionContext.AO中就能够找到,而对于此时的i变量时一直存在于内存中的,
    21              *      而且其值一直是3
    22                     *    c>也就是说,这里的公共作用域里的变量正是这个函数的[[scope]](父级作用域链)属性里的值
    23                     */
    24                    return i;
    25                }
    26            }
    27            return result;
    28        }  
    29        /**
    30         * 当这个函数执行完成之后,这个函数的作用域链会被销毁,但是这个函数的活动对象并不销毁,仍然留在内存中,除非这里的funs变量被销毁,
    31         * 才会释放这个函数里的i变量所占据的空间
    32         */
    33        var funs = createFunction();
    34        for (var i = 0; i < funs.length; i++) {
    35            document.write(funs[i]() + ',');  //3,3,3,
    36        }
    37        
    38        //利用闭包保存状态
    39        function createFunction() {
    40            var result = new Array();
    41            for (var i = 0; i < 3; i++) {
    42                //第一种改造
    43                (function(num) {  //每一次的循环都是一个函数的创建过程,当前这个函数的AO对象里面都保存了num变量
    44                    /**
    45                     * 为什么经过这个改造,它的打印结果就是0,1,2,了呢?一定要从作用域链的角度去理解,这样理解才是最为透彻的
    46                     * 这个匿名函数的Scope = AO + [[scope]],随着循环的进行,相当于创建了三个这样的匿名函数,
    47                     * 传入的这个num参数正是当前Scope里的AO里面的值,由于基本类型变量的传值是按值传递的,所以这里的num记录了
    48                     * 每一次i的值并存入进当前AO里,因此当下面的这个匿名函数在执行时,访问的num值均是这里的AO对象里的num值。
    49                     */
    50                    result[num] = function() {  
    51                        /**
    52                         * 这里的num指代的是第一层closure里的num值,这里的num变量会一直存在于内存当中,
    53                         * 除非重新赋值这里的result[num]为null,也就是说随着匿名函数的消失,它对应的作用域链和变量才会消失。
    54                         */
    55                        return num;  //
    56                    }
    57                    //尽管这里的num变量一直存在于内存当中,但这里的num变量仅仅是当前函数的局部变量,该匿名函数的外部是访问不到num的
    58                })(i);  //当这里的匿名函数执行完成后,这里的num变量不会被立即被销毁,源于里面的匿名函数引用了num变量
    59                
    60                //第二种改造
    61                result[i] = function(num) {  //和上面是一样的,每一次均创建函数并赋值给数组成员,对应的[[scope]]属性值相同,
    62                                             //但是活动对象AO却不同,保存着不同的num值
    63                    return function() {
    64                        //当进入该执行环境时,返回的是不同的第一层closure的num值
    65                        return num;  
    66                    }
    67                }(i);
    68                
    69            }  //当执行完这句代码的时候,这里的i变量就彻底没了
    70            return result;
    71        }
    72    
    73    })(jQuery);

            闭包是JavaScript函数应用的核心,深入理解了闭包,就能解释很多怪异的函数执行现象,当然,也能构造出非常巧妙的设计。

            还有一点要注意,之前在网上看多了很多有关闭包的说法,他们对闭包的理解真是五花八门,对此,我的建议是——一定要从作用域链(或者可以理解为标识符解析)的角度去思考理解闭包。

            注:随时欢迎任何博友对我的理解有误之处作以评论和更正。

  • 相关阅读:
    服务部署 RPC vs RESTful
    模拟浏览器之从 Selenium 到splinter
    windows程序设计 vs2012 新建win32项目
    ubuntu python 安装numpy,scipy.pandas.....
    vmvare 将主机的文件复制到虚拟机系统中 安装WMware tools
    ubuntu 修改root密码
    python 定义类 简单使用
    python 定义函数 两个文件调用函数
    python 定义函数 调用函数
    python windows 安装gensim
  • 原文地址:https://www.cnblogs.com/jinguangguo/p/2632157.html
Copyright © 2011-2022 走看看