如何按值将变量传递给匿名javascript函数?
Posted
技术标签:
【中文标题】如何按值将变量传递给匿名javascript函数?【英文标题】:How to pass a variable by value to an anonymous javascript function? 【发布时间】:2010-11-15 06:56:15 【问题描述】:目标
我想将事件处理程序动态分配给整个站点页面上的某些 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();
可以解决问题,但不能。同样的交易。所以很明显我错过了一些关于这个问题的关键知识,而且可能是非常基本的知识。谢谢。
【问题讨论】:
javascript 总是按值传递和分配。您的问题根本不涉及通过;而是通过闭包捕获变量。 【参考方案1】:我认为你让这变得比它需要的更复杂。如果您所做的只是在鼠标悬停/移出时分配滑动效果,请尝试使用 jquery 的hover 效果。
$("#mytab").hover(function()
$(this).next("div").slideDown("fast");,
function()
$(this).next("div").slideUp("fast");
);
如果您发布了完整的 HTML,我可以告诉您具体的操作方法 :)
【讨论】:
是的,但这不是导致问题的原因。 ...所以我投了反对票?为 OP 的问题提供更简单、更清晰的答案?真的吗? 杰森等人。 - 不要阅读评论的赞成票,这是偶然的,无法撤消 嗨,Jason,您对悬停事件的提示很受赞赏,但它实际上并不能解决问题。不过,它会清理代码,谢谢。我也有点击处理程序,为了清楚起见我省略了也需要绑定。所以滑出/悬停等既不在这里也不在那里,它的目标是应用的事件,这就是问题所在。其他答案提供的闭包理论确实专门解决了这个问题,并且在某种意义上也是“可重用的”,因为无论我试图对 anon 函数做什么,我都必须考虑其参数的范围。【参考方案2】:您需要在每次通过循环时创建一个新变量,以便在您为事件处理程序创建的闭包中捕获它。
但是,仅仅将变量声明移动到循环中并不能做到这一点,因为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]);
【讨论】:
【参考方案3】:这里发生的事情是您的匿名函数正在形成一个闭包,并带走了它们的外部作用域。这意味着当您在异常函数中引用 curTab 时,当事件处理程序运行该函数时,它将在您的外部范围内查找 curTab 的 current 值。这将是您最后分配给 curTab 的任何内容。 (不是你绑定函数时分配的)
你需要做的是改变这个:
$(curDiv).bind("mouseover", function()showHideRangeSlidingTabs(curTab, true); );
到这里:
$(curDiv).bind("mouseover",
(function (mylocalvariable)
return function()
showHideRangeSlidingTabs(mylocalvariable, true);
)(curTab)
);
这会将 curTab 的值复制到外部函数的范围内,内部函数将使用它。这种复制发生在您将内部函数绑定到事件处理程序的同时,因此“mylocalvariable”反映了当时 curTab 的值。然后在下一次循环中,将创建一个具有新范围的新外部函数,并将 curTab 的下一个值复制到其中。
shog9 的回答基本上完成了同样的事情,但他的代码更加简朴。
这有点复杂,但如果你仔细想想,它是有道理的。闭包很奇怪。
编辑:糟糕,忘记返回内部函数。固定。
【讨论】:
【参考方案4】:您可以将变量的值放入不存在的标签中,稍后您可以从那里读取它们。这个 sn-p 是循环体的一部分:
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
【讨论】:
为了兼容HTML5,你可以在tag
之前添加data-
来制作data-tag
,然后你可以使用jQuery的data
方法。以上是关于如何按值将变量传递给匿名javascript函数?的主要内容,如果未能解决你的问题,请参考以下文章