Javascript 通过匿名函数分配鼠标悬停时如何传递局部变量?
我有一个运行onload的设置函数,可以向元素添加一些行为。setup函数将参数传递给mouseover事件,但是这些参数在for循环期间被更改,因为它们是本地引用Javascript 通过匿名函数分配鼠标悬停时如何传递局部变量?,javascript,Javascript,我有一个运行onload的设置函数,可以向元素添加一些行为。setup函数将参数传递给mouseover事件,但是这些参数在for循环期间被更改,因为它们是本地引用 function setupAreas( image, map, lots ) { // obj is a simple wrapper for doc.getElementById var image = obj(image); // image for imagemap var map = obj(map
function setupAreas( image, map, lots ) {
// obj is a simple wrapper for doc.getElementById
var image = obj(image); // image for imagemap
var map = obj(map); // imagemap element
var areas = map.getElementsByTagName('area');
for (var i in areas) {
var area = areas[i]; // imagemap area element
area.id = area.alt;
}
for (var lot_id in lots) {
if (lot_id != 'Lot No' && lot_id != '') {
var area = document.getElementById(lot_id);
if (!area || !area.coords) {
alert('no map coords for lot '+lot_id);
} else {
var coords = area.coords.split(",");
//alert('tag: '+area.tagName+' id: '+lot_id+' area: '+area);
var details = lots[lot_id];
if (details) {
// setup mouseover call with complete details of area
area.onmouseover = function(){ showLot(lot_id, area, coords, details, image, map, areas, lots) };
... snip ...
问题在于,由于for循环,每次迭代时,lot\u id
和area
的引用都会发生变化。结果是任何元素的鼠标悬停事件只给出批次id
和最后一个区域的面积
我不想也不需要jQuery。首选不污染全局命名空间的简单JS解决方案。尝试在闭包中围绕for循环的内容:
for (var lot_id in lots) {
(function(lid){
//contents of for loop - use lid instead of lot_id
})(lot_id);
}
让我知道结果如何
编辑:实际上,您不必环绕整个循环,只需环绕连接事件的线条即可:
(function(lid){
area.onmouseover = function(){ showLot(lid, area, coords, details, image, map, areas, lots) };
})(lot_id);
但是,围绕整个循环可能会防止将来出现错误:)您需要围绕函数创建一个闭包。类似这样的事情可能会有所帮助:
function makeShowLot(lot_id, area, coords, details, image, map, areas, lots) {
return function () {
showLot(lot_id, area, coords, details, image, map, areas, lots);
};
}
然后,改为这样做:
area.onmouseover = makeShowLot(lot_id, area, coords, details, image, map, areas, lots);
makeShowLot
是一个返回函数的函数。返回的函数不接受任何参数;showLot
所需的所有参数都包含在此匿名函数中。正如您正确观察到的,由于闭包,“lot\u id”被捕获,并且对于所有鼠标悬停事件都是相同的。解决这个问题很简单,在分配onmouseover之前,将lot_id存储在另一个本地变量中,比如lotIdForMouseOver,并将其传递给mouseover函数。新的本地变量将在C#中工作,而不是在JavaScript中。在工作中,我做了很多C#,因此产生了混乱
就像pkaeding建议的那样,创建一个helper函数,您应该会很好
另一方面,如果你“反转”你的“如果”检查,你可以去掉嵌套的“如果”。
IMHO,嵌套的if很难遵循
我会这样做的
function setupAreas(image, map, lots)
{
// existing code
for(var lot_id in lots)
{
if(lot_id == 'Lot No' || lot_id == '')
continue;
var area = document.getElementById(lot_id);
if(!area || ! area.coords)
{
alert('no maps for coords for lot ' + lot_id);
continue;
}
var coords = area.coords.split(",");
var details = lots[lot_id];
if(! details)
continue;
//makeMouseOver function takes 'n' arguments and returns a function which
//will call showLot with those same 'n' arguments.
//This is the same suggestion as pkaeding, only that I have exploited 'arguments'
//property to make it simpler.
var makeMouseOver = function()
{
var creationArgs = arguments;
return function() { showLot.apply(null, creationArgs); };
}
area.onmouseover = makeMouseOver(lot_id, area, coords, details, image, map, area, lots);
// more code.
}
}
令人惊讶的是,我已经使用JS很多年了,从来都不知道闭包。