简体   繁体   English

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

[英]How to pass a variable by value to an anonymous javascript function?

The Objective 目标

I want to dynamically assign event handlers to some divs on pages throughout a site. 我想动态地将事件处理程序分配给整个站点的页面上的某些div。

My Method 我的方法

Im using jQuery to bind anonymous functions as handlers for selected div events. 我使用jQuery绑定匿名函数作为选定div事件的处理程序。

The Problem 问题

The code iterates an array of div names and associated urls. 代码迭代div名称和相关URL的数组。 The div name is used to set the binding target ie attach this event handler to this div event. div名称用于设置绑定目标,即将此事件处理程序附加到此div事件。

While the event handlers are successfully bound to each of the div events, the actions triggered by those event handlers only ever target the last item in the array. 当事件处理程序成功绑定到每个div事件时,由这些事件处理程序触发的操作只会定位到数组中的最后一项。

So the idea is that if the user mouses over a given div, it should run a slide-out animation for that div. 所以我的想法是,如果用户将鼠标放在给定的div上,它应该为该div运行一个滑出动画。 But instead, mousing over div1 (rangeTabAll) triggers a slide-out animation for div4 (rangeTabThm). 但是,鼠标悬停在div1(rangeTabAll)上会触发div4的滑出动画(rangeTabThm)。 The same is true for divs 2, 3, etc. The order is unimportant. 对于div 2,3等也是如此。顺序并不重要。 Change the array elements around and events will always target the last element in the array, div4. 更改数组元素,事件将始终以数组div4中的最后一个元素为目标。

My Code - (Uses jQuery) 我的代码 - (使用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);} );
            }
        }

My Theory 我的理论

I'm either not seeing a blindingly obvious syntax error or its a pass by reference problem. 我要么没有看到一个令人眼花缭乱的语法错误或它的引用问题。 Initially i had the following statement to set the value of curTab: 最初我有以下语句来设置curTab的值:

curTab=inlineRangeNavUrls[i][0];

So when the problem occured i figured that as i changed (via for loop iteration) the reference to curTab, i was in fact changing the reference for all previous anonymous function event handlers to the new curTab value as well.... which is why event handlers always targeted the last div. 因此,当问题发生时,我认为当我改变(通过循环迭代)对curTab的引用时,我实际上所有先前的匿名函数事件处理程序的引用更改为新的curTab值....这就是为什么事件处理程序始终以最后一个div为目标。

So what i really needed to do was pass the curTab value to the anonymous function event handlers not the curTab object reference. 所以我真正需要做的是将curTab 传递给匿名函数事件处理程序而不是curTab 对象引用。

So i thought: 所以我认为:

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

would fix the problem, but it doesn't. 会解决问题,但事实并非如此。 Same deal. 同样的交易。 So clearly im missing some key, and probably very basic, knowledge regarding the problem. 所以很明显我错过了关于这个问题的一些关键,也许是非常基本的知识。 Thanks. 谢谢。

You need to create a new variable on each pass through the loop, so that it'll get captured in the closures you're creating for the event handlers. 您需要在循环的每次传递中创建一个新变量,以便它将在您为事件处理程序创建的闭包中捕获。

However, merely moving the variable declaration into the loop won't accomplish this, because JavaScript doesn't introduce a new scope for arbitrary blocks . 但是,仅将变量声明移动到循环中将无法实现此目的,因为JavaScript不会为任意块引入新范围

One easy way to force the introduction of a new scope is to use another anonymous function: 强制引入新范围的一种简单方法是使用另一个匿名函数:

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 , you can actually clean this up quite a bit using jQuery's built-in hover() function: 正如杰森建议的那样 ,你可以使用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]); 
}

what's going on here is that your anonmymous functions are forming a closure, and taking their outer scope with them. 这里发生的事情是你的无数函数正在形成一个闭包,并将它们的外部范围与它们结合起来。 That means that when you reference curTab inside your anomymous function, when the event handler runs that function, it's going to look up the current value of curTab in your outer scope. 这意味着当你在anomymous函数中引用curTab时,当事件处理程序运行该函数时,它将在你的外部作用域中查找curTab的当前值。 That will be whatever you last assigned to curTab. 这将是你最后分配给curTab的任何东西。 (not what was assigned at the time you binded the function) (不是在绑定功能时分配的内容)

what you need to do is change this: 你需要做的是改变这个:

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

to this: 对此:

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

this will copy the value of curTab into the scope of the outer function, which the inner function will take with it. 这会将curTab的值复制到外部函数的范围内,内部函数将使用它。 This copying happens at the same time that you're binding the inner function to the event handler, so "mylocalvariable" reflects the value of curTab at that time. 这种复制发生在您将内部函数绑定到事件处理程序的同时,因此“mylocalvariable”反映了当时curTab的值。 Then next time around the loop, a new outer function, with a new scope will be created, and the next value of curTab copied into it. 然后下一次循环,将创建一个带有新范围的新外部函数,并将curTab的下一个值复制到其中。

shog9's answer accomplishes basically the same thing, but his code is a little more austere. shog9的答案基本上完成了同样的事情,但他的代码更加严谨。

it's kinda complicated, but it makes sense if you think about it. 它有点复杂,但如果你想一想就有意义。 Closures are weird. 关闭很奇怪。

edit: oops, forgot to return the inner function. 编辑:oops,忘了返回内部函数。 Fixed. 固定。

I think you're making this more complicated than it needs to be. 我认为你让它变得比它需要的更复杂。 If all you're doing is assigning a sliding effect on mouseover/out then try the hover effect with jquery. 如果你所做的只是在鼠标悬停/输出上分配滑动效果,那么用jquery尝试悬停效果。

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

If you posted your full HTML I could tell you exactly how to do it :) 如果您发布了完整的HTML,我可以告诉您具体的操作方法:)

You can put your variable's value into a non existing tag, and later you can read them from there. 您可以将变量的值放入非现有标记中,稍后您可以从那里读取它们。 This snippet is part of a loop body: 此代码段是循环体的一部分:

 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM