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

发布于 2024-07-29 02:06:40 字数 1723 浏览 10 评论 0原文

目标

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

我的方法

我使用 jQuery 将匿名函数绑定为选定 div 事件的处理程序。

问题

该代码迭代 div 名称和关联 url 的数组。 div 名称用于设置绑定目标,即将此事件处理程序附加到此 div 事件。

虽然事件处理程序已成功绑定到每个 div 事件,但这些事件处理程序触发的操作仅针对数组中的最后一项。

因此,我们的想法是,如果用户将鼠标悬停在给定的 div 上,它应该为该 div 运行滑出动画。 但相反,将鼠标悬停在 div1 (rangeTabAll) 上会触发 div4 (rangeTabThm) 的滑出动画。 div 2、3 等也是如此。顺序并不重要。 更改数组元素,事件将始终针对数组中的最后一个元素 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 值......这就是为什么事件处理程序始终以最后一个 div 为目标。

所以我真正需要做的是将 curTab value 传递给匿名函数事件处理程序,而不是 curTab object 引用。

所以我想:

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

可以解决问题,但事实并非如此。 同样的交易。 很明显,我缺少一些有关该问题的关键知识,而且可能是非常基本的知识。 谢谢。

The Objective

I want to dynamically assign event handlers to some divs on pages throughout a site.

My Method

Im using jQuery to bind anonymous functions as handlers for selected div events.

The Problem

The code iterates an array of div names and associated urls. The div name is used to set the binding target i.e. attach this event handler to this div event.

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.

So the idea is that if the user mouses over a given div, it should run a slide-out animation for that div. But instead, mousing over div1 (rangeTabAll) triggers a slide-out animation for div4 (rangeTabThm). The same is true for divs 2, 3, etc. The order is unimportant. Change the array elements around and events will always target the last element in the array, div4.

My Code - (Uses 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=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.

So what i really needed to do was pass the curTab value to the anonymous function event handlers not the curTab object reference.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

渔村楼浪 2024-08-05 02:06:40

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

但是,仅仅将变量声明移动到循环中并不能实现此目的,因为 JavaScript 不会为任意块引入新的作用域

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

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
  }
}

正如 Jason 建议的,你实际上可以使用 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]); 
}

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.

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:

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]); 
}
翻了热茶 2024-08-05 02:06:40

这里发生的事情是,您的匿名函数正在形成一个闭包,并带走它们的外部作用域。 这意味着当您在匿名函数内引用 curTab 时,当事件处理程序运行该函数时,它将在外部作用域中查找 curTab 的当前值。 这将是您最后分配给 curTab 的任何内容。 (不是在绑定函数时分配的值)

您需要做的是将 this: 更改

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

为 this:

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

this 会将 curTab 的值复制到外部函数的范围中,内部函数将随之复制。 此复制发生在您将内部函数绑定到事件处理程序的同时,因此“mylocalvariable”反映了当时 curTab 的值。 然后,下次循环时,将创建一个具有新作用域的新外部函数,并将 curTab 的下一个值复制到其中。

shog9 的答案基本上完成了同样的事情,但他的代码更加简洁。

这有点复杂,但如果你仔细想想,那就很有意义了。 关闭很奇怪。

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

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. That will be whatever you last assigned to 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. 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. 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.

shog9's answer accomplishes basically the same thing, but his code is a little more austere.

it's kinda complicated, but it makes sense if you think about it. Closures are weird.

edit: oops, forgot to return the inner function. Fixed.

飘过的浮云 2024-08-05 02:06:40

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

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

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

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.

$("#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 :)

夏の忆 2024-08-05 02:06:40

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

 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文