• 谈谈我对JS闭包的理解


    这一篇博客承接上一篇,如果大家没看上一篇,建议看看.....直通车..... 好吧,咱们一起来看看这个闭包,这次我们的重点并不是弄明白闭包是什么?而是搞清楚JS的闭包是怎么产生的。接着上一篇博客的示例:

    var a = function(x){
        var b = 'bb';
        var inner = function(){
            var c = 'cc';
        };
        return b;
    };

    当a函数执行到给inner变量赋值匿名函数之后,形成下面的引用关系,直接复用上次博客的图:

    从上图很容易看出,这时候inner函数对象的[[Scope]]内部属性引用着函数a在执行期的活动对象(这里包含了a函数的全部局部变量)和全局作用域。如果这时候我们把这个inner函数传递出去,如下代码:

    var a = function(x){
        var b = 'bb';
        var inner = function(){
            var c = 'cc';
        };
        return inner ;
    };
    
    var closure = a();

    这段代码意思是:执行a函数,把inner函数返回,并把它赋值给closure变量,这时候全局变量closure和之前的局部变量inner引用同一个函数,大家可以运行下面的代码:

    var a = function(x){
        var b = 'bb';
        var inner = function(){
            var c = 'cc';
            console.log(inner === closure);
        };
        return inner ;
    };
    
    var closure = a();
    
    closure();/*输出控制台:true*/

    这段代码证实了之前所言变量closure和inner引用同一个函数对象,换句话说就是,名为inner的函数和名为closure的函数是同一个函数,closure函数的作用域链和inner函数的当然也是一样一样的,如下图:

    这时候再结合上一篇博客,大家该明白了,为什么当a函数返回后,closure函数还可以使用a函数内部的局部变量了吧。

    这时候还有一个问题,那就是类比其他语言时,例如C语言,当一个函数执行完毕返回后,应该释放所有这个函数执行期所占用的内存资源,当然也包含它的局部变量了,如果不这么做,不是会造成内存泄露么?JS解释器当然会释放,但是JS解释器是这样做的:当函数执行完毕后,由JS解释器的垃圾回收机制来释放内存,它的工作机制大体上是这样的:它会定期执行,判断一块被占用的内存区域是否还被可用变量所引用,如果没有,直接释放内存,如果有,那就不释放。其实我们在编写JS代码时是没有办法直接销毁对象所占用的内存空间的,内存的释放基本依赖JS的垃圾回收机制。那么有人会说delete运算符,其实delete运算符也无法销毁对象所占用的内存空间,如下示例:

    var a = {k:'占用内存'};
    var b = a;
    
    delete a;
    
    
    
    console.log(b);/*{k:'占用内存'}对象并未被释放*/
    
    console.log(a);/*语法错误,a is not defined*/

    那么delete到底做了什么呢?它销毁了a变量,这样原来变量a和b都引用{k:'占用内存'}对象所占的内存区域,现在销毁a后,就只有b引用这块内存区域了。如果我们再执行下一条运算:

    delete b;

    这时候,就没有任何可用变量引用{k:'占用内存'}对象所占的内存区域了,垃圾回收机制自然会识别并释放资源。

    回到闭包的话题上来,如果不产生闭包的话,a函数执行完后。a函数的执行期上下文自然会被垃圾回收机制所识别释放,a函数内部的的局部变量inner函数对象也会被释放掉,这点毫无疑问,不会留下任何内存泄露的问题。但是,如果将inner函数对象作为结果返回并赋值给了closure,产生了闭包,那么这个函数对象将不会被销毁,它的内部变量[[Scope]]引用的作用域链当然也就不会被销毁。一切都这么自然而然的发生了........^_^

    不过JS的闭包,如果使用不当,是很容易造成内存泄露的,但是鉴于它的好处,我们既要使用它,也要避免造成内存泄露,所以深刻的理解它很重要^_^

    好吧,今天就这些。如有错误,请轻拍............

  • 相关阅读:
    form在两个div之间会有间距 得加上style="margin:0px"
    JavaScript trim函数大赏 (转)
    js prototype
    aptana对齐快捷键ctrl+shift+f
    深入浅出JSON
    ie和火狐的一些区分
    javascript”面向对象编程” 2聊聊对象的事
    _#【media type / media query】
    【ajax】接口数据赋给全局变量
    _#【HTML 优化】使用相对 URL
  • 原文地址:https://www.cnblogs.com/liubingblog/p/4335907.html
Copyright © 2020-2023  润新知