代码之家  ›  专栏  ›  技术社区  ›  rism

如何将变量按值传递给匿名javascript函数?

  •  22
  • rism  · 技术社区  · 15 年前

    目的

    我想动态地将事件处理程序分配给整个站点页面上的某些div。

    我的方法

    我使用jquery绑定匿名函数作为所选DIV事件的处理程序。

    问题

    代码迭代一个DIV名称数组和相关的URL。DIV名称用于设置绑定目标,即将此事件处理程序附加到此DIV事件。

    当事件处理程序成功绑定到每个DIV事件时,由这些事件处理程序触发的操作始终只针对数组中的最后一个项。

    因此,我们的想法是,如果用户鼠标悬停在一个给定的DIV上,那么它应该为该DIV运行一个滑出动画。但是,鼠标悬停在DIV1(RangeTaball)上会触发DIV4(RangeTabThm)的滑出动画。第二、三等舱也是如此,顺序无关紧要。更改周围的数组元素,事件始终以数组中的最后一个元素div4为目标。

    我的代码-(使用jquery)

    var curTab, curDiv;
    var inlineRangeNavUrls=[['rangeTabAll','range_all.html'],['rangeTabRem','range_remedial.html'],
                    ['rangeTabGym','range_gym.html'],['rangeTabThm','range_thermal.html']];
            for (var i=0;i<inlineRangeNavUrls.length;i++)
            {
                curTab=(inlineRangeNavUrls[i][0]).toString();
                curDiv='#' + curTab;
                if  ($(curDiv).length)
                {
                    $(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );
                    $(curDiv).bind("mouseout", function(){showHideRangeSlidingTabs(curTab, false);} );
                }
            }
    

    我的理论

    我或者没有看到一个明显的语法错误,或者它是一个传递引用问题。 最初我有以下语句来设置curtab的值:

    curTab=inlineRangeNavUrls[i][0];
    

    所以当问题发生时,我发现当我改变(通过for循环迭代)对curtab的引用时,我实际上 改变 以前所有匿名函数事件处理程序对新curtab值的引用…这就是为什么事件处理程序总是以最后一个分区为目标。

    所以我真正需要做的是通过Curtab 价值 匿名函数事件处理程序,而不是curtab 对象 参考文献。

    所以我想:

    curTab=(inlineRangeNavUrls[i][0]).toString();
    

    会解决问题的,但不会。同样的道理。所以很明显我遗漏了一些关于这个问题的基本知识。谢谢。

    4 回复  |  直到 13 年前
        1
  •  23
  •   Community CDub    7 年前

    您需要在每次传递循环时创建一个新的变量,以便在为事件处理程序创建的闭包中捕获它。

    但是,仅仅将变量声明移动到循环中并不能实现这一点,因为 JavaScript doesn't introduce a new scope for arbitrary blocks .

    强制引入新作用域的一个简单方法是使用另一个匿名函数:

    for (var i=0;i<inlineRangeNavUrls.length;i++)
    {
      curDiv='#' + inlineRangeNavUrls[i][1];
      if ($(curDiv).length)
      {
        (function(curTab)
        {
          $(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );
          $(curDiv).bind("mouseout", function(){showHideRangeSlidingTabs(curTab, false);} );
        })(inlineRangeNavUrls[i][0]); // pass as argument to anonymous function - this will introduce a new scope
      }
    }
    

    As Jason suggests 实际上,您可以使用jquery的内置功能来清理这个问题。 hover() 功能:

    for (var i=0;i<inlineRangeNavUrls.length;i++)
    {
      (function(curTab) // introduce a new scope
      {
      $('#' + inlineRangeNavUrls[i][1])
        .hover(
          function(){showHideRangeSlidingTabs(curTab, true);},
          function(){showHideRangeSlidingTabs(curTab, false);} 
        );
      // establish per-loop variable by passsing as argument to anonymous function
      })(inlineRangeNavUrls[i][0]); 
    }
    
        2
  •  17
  •   Breton    15 年前

    这里发生的是异常函数正在形成一个闭包,并将它们的外部作用域与之结合。这意味着当您在异常函数中引用curtab时,当事件处理程序运行该函数时,它将查找 现在的 外部作用域中curtab的值。这将是您上次分配给curtab的内容。(不是绑定函数时分配的内容)

    你需要做的是改变这一点:

    $(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );
    

    对此:

    $(curDiv).bind("mouseover", 
        (function (mylocalvariable) { 
            return function(){
                showHideRangeSlidingTabs(mylocalvariable, true);
            } 
        })(curTab) 
    );
    

    这将把curtab的值复制到外部函数的作用域中,内部函数将使用该作用域。这种复制发生在您将内部函数绑定到事件处理程序的同时,因此“mylocalvariable”反映了当时curtab的值。然后,下次在循环中,将创建一个具有新作用域的新外部函数,并将curtab的下一个值复制到该函数中。

    Shog9的回答基本上完成了相同的事情,但他的代码更为简朴。

    这有点复杂,但如果你考虑一下就有意义了。封口很奇怪。

    编辑:哎呀,忘记返回内部函数了。固定的。

        3
  •  1
  •   Jason    15 年前

    我认为你让事情变得比需要的更复杂了。如果您所做的只是在鼠标悬停/悬停时指定滑动效果,请尝试 hover 使用jquery效果。

    $("#mytab").hover(function(){
        $(this).next("div").slideDown("fast");},
      function(){
        $(this).next("div").slideUp("fast");
    });
    

    如果您发布了完整的HTML,我可以告诉您具体的方法:)

        4
  •  1
  •   Gyuri    13 年前

    您可以将变量的值放入一个不存在的标记中,稍后您可以从中读取它们。此代码段是循环体的一部分:

     s = introduction.introductions[page * 6 + i][0]; //The variables content
     $('#intro_img_'+i).attr('tag' , s);              //Store them in a tag named tag
     $('#intro_img_'+i).click( function() {introduction.selectTemplate(this, $(this).attr('tag'));}  );  //retrieve the stored data