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函数应用的核心,深入理解了闭包,就能解释很多怪异的函数执行现象,当然,也能构造出非常巧妙的设计。

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

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

  • 相关阅读:
    基于perl的网络爬虫
    ios cell展示可滑动的图片
    iOS计算字符串的宽度高度
    swift水波效果
    iOS添加另一个控制器的时候要注意啊
    swift隐藏显示导航栏的底线
    swift集成alamofire的简单封装
    tableview详细介绍
    xmpp xml基本语义
    xmpp SASL 定义
  • 原文地址:https://www.cnblogs.com/jinguangguo/p/2632157.html
Copyright © 2011-2022 走看看