duyinghua518 2012-08-09 14:47
浏览 192
已采纳

有关闭包 事件的引用传址问题?求解答

我们都知道javascript中的对象类型是传引用地址的而不是传值的,我今天遇到个不明白的问题就是当我把代码在点击事件写的时候令我以外的传值了,而我写到循环里面却是传的地址代码如下
这里是普通循环触发,结果是2s后三次alert,每次都是2,这是和预期的一样last给bb传递了引用地址,就是当last改变时候bb也改变了

//普通循环demo for(i=0;i<3;i++){ var aa = {name:"aa"}; aa.name = i; last = aa; var bb = last; setTimeout(function() { alert(bb.name); }, 2000); }


下面是事件触发 就是在2s内迅速点击鼠标3次,结果2s后三次alert依次是0,1,2。我很不解,为什么这里last传给bb的不是引用地址呢??bb为什么不改变呢?很奇怪望讨论

//事件demo var i = 0; var last = null; document.addEventListener("click", function(event) { var aa = {name:"aa"}; aa.name = i; last = aa; var bb = last; setTimeout(function() { alert(bb.name); }, 2000); i++; });

  • 写回答

2条回答 默认 最新

  • clxy大叔 2012-08-11 16:12
    关注

    我来尝试解释这个现象。

    先说办法,就是把这句

    [code="js"] alert(bb.name); [/code]

    都改成

    [code="js"]alert(bb.name + " - " + last.name); [/code]

    再执行,你会看到

    • 循环那例子连续alert了3次“2 - 2”,
    • 事件那例子分别alert了“0 - 2”,“1 - 2”,“2 - 2”。

    我认为原因是,[b][color=green]每次事件处理都有自己独立的context,其中保存了局部变量,比如bb。setTimeout中的function也是在这个context下执行的。[/color][/b]

    • 循环例子中只有一个默认的context,循环结束后bb被改成2,所以三次都是2。
    • 事件的例子中先后又有了3个独立的context,每个context里面的局部变量bb分别是0,1,2。但全局变量last还都是被改成了2。所以结果如上。

    我又把第二个例子改成这样
    [code="html"]

    //事件demo var i = 0; var last = null; document.addEventListener("click", function(event) { var aa = {name:"aa"}; aa.name = i; last = aa; var bb = last; var x = (i==0)?2000:1000; setTimeout(function() { alert(bb.name + " - " + last.name); }, x); i++; });


    [/code]

    也就是让第二次点击的timeout先到期,得到的结果是“1 - 1”,“0 - 1”这样的顺序。似乎也能验证上面的论点。

    所以,这个恐怕不是值传递还是引用传递的问题,而是执行context混合作用域的问题。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办