js 多按钮事件响应 传参值重复问题

对于以下函数,alert(x)的值全为42,为什么,怎么解决functioninitButtons(){varx=0;vary=0;varw=1512;varh=1560... 对于以下函数,alert(x)的值全为42,为什么,怎么解决
function initButtons()
{
var x = 0;
var y = 0;
var w = 1512;
var h = 1560;
var button = new Array();
for(y = 0; y * 30< h; y++)
for(x = 0; x * 36 < w; x++)
{
var n = (1 + y * 40 + x);
button[n] = document.createElement("input");
button[n].type = "button";
button[n].id = "detail" + n;
button[n].addEventListener('mouseover',function(){alert(x);});
button[n].addEventListener('mouseout',hideD);
button[n].style.cssText = "position:absolute;top:" + ((y + 1) * 30 - 8) + ";left:" + ((x + 1) * 36 - 8) + ";width:10;height:15;background:transparent;";
document.getElementById("buttons").appendChild(button[n]);
}
}
展开
 我来答
Aileen0509
2016-08-09 · TA获得超过1492个赞
知道小有建树答主
回答量:371
采纳率:0%
帮助的人:416万
展开全部

这个问题是你在循环中的闭包导致的。

下面代码中,因为 mouseover 的回调函数形成了一个闭包,所以闭包中的 x 是调用的闭包外面的变量 x,而在循环结束之后,这个x 的值是42,所以无论在循环中的哪一次绑定事件,最后 x 都是42.

button[n].addEventListener( 'mouseover', function() { alert(x); } );

可以通过以下两种方法调整代码修复这个问题:

第一种:不要在循环中创建闭包,这是非常不推荐的写法,如果你用 JSHint 做代码检测,这个会报出一条警告。因为这种方法很危险,容易埋下隐患。所以要把 handler 函数定义在 initButtons 外面。这样有两种写法:

下面是第一种写法:

// 在 initButtons 函数外面定义函数 handler 

function handler( x ) {

    console.log( 'click', x );

}

// 将事件绑定的位置改写成这样

button[n].addEventListener( 'mouseover', handler.bind( button[n], x ) );

下面是第二种写法:

// 在 initButtons 函数外面定义函数 handler

function handler( x ) {

    return function() {       
     
        console.log( x );
        
    };
    
}

// 将事件绑定的位置改写成这样。

button[n].addEventListener( 'mouseover', handler( x ) );


第二种:依然在循环中创建闭包,但是改变传值方式


// 将事件绑定部分改成这样

button[n].addEventListener( 'mouseover', ( function( x ) {
    
    return function() {
        
        console.log( x );
    
    };

} )( x ) );
追问
  1. 首先膜拜一下大牛,提供了三种方法,经验证都是可行解

  2. 其次,说一下我出现这种问题的根本原因:

    我错以为每次调用addEventListener函数,x的当前值都会自动被记录下来,而实际上并没有。我这样写回调函数只是单纯提供一个函数,这三种方法之所以能行,是因为这样写能在调用addEventListener函数的同时,回调函数部分会被执行一次,在返回一个函数的同时,将当前x的值也传递了过去~简直太完美!

推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式