开发者社区> 问答> 正文

在js的一个函数内部再执行事件函数绑定语句,事件函数内引用此函数的局部变量,为何外部函数运行后局部变量不会销毁?

代码:

$button1=$("#button1");
$button2=$("#button2");

function Panel(){}

Panel.prototype.activate=function(){
      var a=1;
      $button2.click(function(){
       a+=1;
       });
}

$button1.click(function(){
       new Panel().activate();
});

如题我在Panel.prototype.activate内为button2的单击事件绑定了函数,该函数内部引用了Panel.prototype.activate的局部变量a,然后我为button1元素的单击事件绑定Panel.prototype.activate函数。
之后进行操作:
1 单击button1:执行 Panel.prototype.activate函数,且botton2的单击事件被绑定函数
2 单击button2:操作Panel.prototype.activate的局部变量a

为什么局部变量a会一直存在?按道理步骤1, Panel.prototype.activate函数执行后a即被销毁?

请问这种情况这与js的闭包是一个概念吗?
我是一个新手,关于闭包,对其理解是:内部函数的执行体若引用外部函数的局部变量,并且return此变量,那么执行内部函数后,此局部变量不会被销毁。
但是问题中这种情况如何解释?

展开
收起
小旋风柴进 2016-05-27 11:09:18 3245 0
1 条回答
写回答
取消 提交回答
  • 闭包是关于变量作用域链的
    闭包建立在函数声明阶段,而非执行阶段
    闭包是依附在函数对象上的
    JS垃圾回收是基于引用计数的
    函数执行时生成的局部变量在函数执行完毕后就会从执行栈中清除掉,但不意味着者可以GC掉,还要看其是否被引用
    那么我们回到问题
    `
    $button1=$("#button1");
    $button2=$("#button2");`
    声明了$button1变量和$button2变量

    function Panel(){}
    Panel.prototype.activate=function(){
          var a=1;
          $button2.click(function(){
           a+=1;
           });
    }

    定义了Panel函数,声明了一个匿名函数A,在匿名函数内部声明了一个内部变量a,引用了变量$button2,并在内部同事声明了一个匿名函数A1,将会使用到其定义时所处的函数的内部变量a;
    至此就会形成2个闭包,
    [闭包1]一个针对Panel函数原型对象的activate方法(函数)的闭包-可以能访问非内部变量$button2;
    [闭包2] 一个针对匿名函数的闭包-可以/需要访问activate函数的内部变量a

    $button1.click(function(){
           new Panel().activate();
    });

    声明了一个匿名函数B,其需要访问Panel构造函数,所以匿名函数还有又构成一个闭包[闭包3]-可以/需要范围访问Panel构造函数

    在函数声明阶段完成,也就是词法作用域分析结束后
    开始代码的执行,
    为Panel函数原型添加了一个方法activate并将其指向声明的匿名函数A
    为$button1绑定click事件回调匿名函数B

    当$button1触发click事件后,匿名函数B被执行,利用闭包能够访问到Panel函数,进而新建了一个Panel对象,并执行了activate方法,初始化变量a,用到闭包能够访问到$button2,为$button2绑定click事件回调匿名函数A1.
    当$button2触发click事件,匿名函数A1就被访问,利用前面的闭包能够访问a
    匿名函数A1/匿名函数B分别绑定在$button2,$button1上的,这个2个对象都函数都还有引用,所以执行完了以后函数对象不会被GC掉,那么闭包也就保留着,闭包保留着,那么对其中的变量就会有引用存在,那么变量就不会被清除的

    闭包中的变量并不会随着函数的执行完毕而被清除掉,反而会一直保留着,除非这个闭包被清除-也就是闭包中涉及的变量再也没有被别的函数引用到。
    例如

    function add10(init){
        var a=10;
        var add=function(){
            a+=10;
        }
        add();
        return a;
    }
    console.log(add10(10));//输出20

    add函数就会形成一个闭包,可以/需要访问变量a
    但在add10函数执行完了后,闭包将会消失,因为没有其它对象会引用到函数add,那么可以GC掉add,闭包也就失去了其依赖的对象,也就会被GC掉

    2019-07-17 19:17:25
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
JavaScript面向对象的程序设计 立即下载
Delivering Javascript to World 立即下载
编程语言如何演化-以JS的private为例 立即下载