zoukankan      html  css  js  c++  java
  • 关于闭包

    在看下面的内容,先要对执行环境(变量对象,作用域链)等有所了解。可以参考我之前写的执行环境。
    关于本文的闭包内容,首先推荐几篇资料。

    1预编译
    征途书上的资料,粗略的讲了下词法分析和语法分析,http://ajava.org/readbook/js/jszt/17035.html
    经过编译阶段的准备,JavaScript代码在内存中已经被构建为语法树,然后JavaScript引擎就会根据这个语法树结构边解释边执行了。
    在解释过程中,JavaScript引擎是严格 按着作用域机制来执行的。JavaScript语法采用的是词法作用域,也就是说JavaScript的变量和函数作用域是在定义时决定的,而不是执行时 决定的,由于词法作用域取决于源代码结构,所以JavaScript解释器只需要通过静态分析就能确定每个变量、函数的作用域,这种作用域也称为静态作用域。
    当JavaScript解释器执行每个函数时,先创建一个执行环境,在这个虚拟环境中创建一个调用对象,在这个对象内存储着当前域中所有局部变量、参数、嵌套函数、外部引用和父级引用列表upvalue等语法分析结构。
    实际上,通过声明语句定义的变量和函数在预编译 期的语法分析中就已经存储到符号表中了,然后把它们与调用对象中的同名属性进行映射即可
    调用对象的生命周期与函数的生命周期是一致的,当函数调用完毕且 没有外部引用的情况下,会自动被JavaScript引擎当做垃圾进行回收。

    2函数的Variable object在预编译阶段被创建的
    也就是上面说的 声明语句定义的变量和函数在预编译 期的语法分析中就已经存储到符号表中了
    一个网页上看到的 http://stephenwalther.com/blog/archive/2008/02/26/javascript-magic-properties-using-count-proto-and-parent.aspx
    A local variable defined in a function becomes a property of the function’s Variable object. The function’s Variable object gets created when a function is interpreted (not when the function is executed).
    函数的局部变量是函数的 变量对象 的属性,函数的变量对象 是在函数解释的时候被创建的,不是在函数执行的时候才开始创建的。

    3
    http://hi.baidu.com/lmzxf/blog/item/5841c7ef1c43d427adafd52c.html
    ,一个比较详细的流程。尤其那张图 


    4
    经典的闭包文章http://jibbering.com/faq/notes/closures/
    This would normally be the case upon exiting an execution context. The scope chain structure, the Activation/Variable object and any objects created within the execution context, including function objects, would no longer be accessible and so would become available for garbage collection.
    当退出执行环境的时候,任何在执行环境中创建的活动对象,作用域链,对象,以及函数对象,都不再可以被访问。这时就会被垃圾收集
    相对于函数来说,就是函数退出时,所有在函数中创建的对象都会被销毁,也就是没有内存保留。函数只被作为了一个运算过程。

    5winter大神的 http://www.cnblogs.com/winter-cn/archive/2008/07/07/1237168.html

    -

    -

    -

    -

    -

    实例,结合js高级2 上的第七章 闭包

    Closures are functions that have access to variables from another function ’ s scope。

    1关于静态作用域 

    function createComparisonFunction(propertyName) {
    return function(object1, object2){
    var value1 = object1[propertyName];
    var value2 =
    object2[propertyName];
    ........
    }
    }

    这里的着色的代码部分,能够访问到外部函数的参数propertyName,即使这个匿名函数被return到了其他地方。
    为什么呢?这是因为js是静态作用域的原因。这个匿名函数的作用域已经在定义时就决定了。

    2  关于执行过程
    当一个函数被调用的时候,就会创建一个执行环境,这个执行环境有一个[[scope]]属性,这个属性初始化了作用域链,活动对象被创建并添加到作用域链的顶部,下面是函数和图。其中的作用域链是一系列指向变量对象的指针。

    function compare(value1, value2){
    if (value1 < value2){return -1;}
    }
    var result = compare(5, 10);
    


    一旦函数执行结束,活动对象就会被摧毁,只剩下全局对象在内存中。

    3  闭包
    如果第一个函数加上以下代码,那情况就不一样了

    function createComparisonFunction(propertyName) {
    return function(object1){
    var value1 = object1[propertyName];
    ........
    }
    }
    
    var compareNames = createComparisonFunction(“name”);
    
    var result = compareNames({ name: “Nicholas” });
    
    compareNames = null;
    


    var compareNames = createComparisonFunction(“name”);这个是一个闭包

    执行这个函数时,创建createComparisonFunction函数的活动对象,创建匿名函数对象,这个匿名函数对象的作用域链引用了外部函数createComparisonFunction的活动对象
    如果这个匿名函数不被return,赋值给全局变量的话,那么外部函数的活动对象会像2中一样,随着函数的执行结束而销毁。
    而return给全局对象后,这createComparisonFunction函数的活动对象就不会被销毁。因为根据垃圾收集机制。存在引用的话就不会被回收。
    此时因为compareNames函数对象能被访问到,同时根据上面1中静态作用域的原因,这个函数对象的作用域链已经在创建时初始化了,保存了外部函数的活动对象
    因为活动对象没有被释放掉,所以内存中一直保存了。

    var result = compareNames({ name: “Nicholas” }, { name: “Greg”});
    执行这步时,创建compareNames函数的活动对象,执行结束后,被回收。

    如何释放掉内存呢?让引用指向别的地方就行了。compareNames现在引用函数对象,所以内存没法释放。compareNames=null就行了。

  • 相关阅读:
    openwrt 相关文章
    负载均衡相关文章
    Today's Progress
    Rodrigues formula is beautiful, but uneven to sine and cosine. (zz Berkeley's Page)
    Camera Calibration in detail
    Fundamental Matrix in Epipolar
    Camera Calibration's fx and fy do Cares in SLAM
    FilterEngine::apply
    FilterEngine 类解析——OpenCV图像滤波核心引擎(zz)
    gaussBlur
  • 原文地址:https://www.cnblogs.com/lunalord/p/1997925.html
Copyright © 2011-2022 走看看