Javascript 添加';单击';循环中的事件侦听器
重构html标记中的标准Javascript 添加';单击';循环中的事件侦听器,javascript,events,loops,click,listeners,Javascript,Events,Loops,Click,Listeners,重构html标记中的标准onClick,侦听器面临代码问题: var td; for (var t=1;t<8;t++){ td = document.getElementById('td'+t); if (typeof window.addEventListener==='function'){ td.addEventListener('click',function(){ c
onClick
,侦听器面临代码问题:
var td;
for (var t=1;t<8;t++){
td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(td);
})}
}
var-td;
for(var t=1;t据我所知,它是由于闭包而发生的…您在for语句的范围内分配事件处理程序。单击“发生”时,它会获取for范围内的最后一个版本if TD变量并将其写入日志。您需要将事件侦听器的分配包装在闭包中,类似于:
var td;
for (var t = 1; t < 8; t++){
td = document.getElementById('td'+t);
if (typeof window.addEventListener === 'function'){
(function (_td) {
td.addEventListener('click', function(){
console.log(_td);
});
})(td);
}
}
var-td;
对于(var t=1;t<8;t++){
td=document.getElementById('td'+t);
if(typeof window.addEventListener==='function'){
(功能){
td.addEventListener('click',function(){
console.log(_td);
});
})(td);
}
}
以下各项应按预期工作:
for (var t=1;t<8;t++){
var td;
td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(this);
})}
}
用于(var t=1;t因此,这里发生的事情是,您将变量“td”保留在事件侦听器函数的作用域中。只有一个“td”实例,并且每次for循环迭代时都会更新它。因此,当for循环完成时,td的值现在设置为元素“#td7”,并且您的事件处理程序只是记录cutd的当前值
在上面的示例中,您可以简单地记录“this”:
var td;
for (var t=1;t<8;t++){
td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(this);
});
}
}
var-td;
对于(var t=1;t发生了什么
变量td
是在事件处理程序之外定义的,因此,当您单击单元格时,您将记录其上次设置的值
更严格地说:每个事件处理程序函数都是一个闭包——一个引用外部范围变量的函数
通解
此类问题的一般解决方案是从包装函数返回事件处理程序,并将要“修复”的变量作为参数传递:
td.addEventListener('click',函数(wrapTD){
返回函数(){console.log(wrapTD);}
}(td);;
参数现在绑定到被调用的包装器函数的作用域
更简单的解决方案:使用此
但是,还有一个更简单的选项。在事件处理程序中,此
设置为定义处理程序的元素,因此您可以使用此
而不是td
:
td.addEventListener('click',function(){
console.log(this);
});
更简单的是:没有循环!
最后,您可以完全摆脱for
循环,并在整个表上设置单个事件处理程序:
var table=document.getElementById('my-table');
表.addEventListener('click',函数(e){
if(e.target.nodeName.toUpperCase()!=“TD”)返回;
var td=e.target;
console.log(td);
});
对于较大的表,这是一个更好的解决方案,因为您将用一个事件处理程序替换多个事件处理程序。请注意,如果您将文本包装在另一个元素中,则需要调整此设置,以检查目标元素是否是td
的后代。您可以尝试在循环内声明var
,或者明确地尝试相同的代码吗对于td1 after循环。听起来很愚蠢,让我们试试。@Azodious,是的,已经尝试过了,结果是sameif显式指定(硬代码),例如,td1
它可以工作,可以尝试创建长度为8的数组。用td
对象填充它,然后尝试将侦听器附加到索引。也许是这样。但我预计每个td:td1、td2、…td8都会被填充,可以工作。谢谢。关于闭包的更多问题:\u td
等于td
?闭包只是一个立即执行的函数,因此在执行时保留变量的状态。我们通过将td
的\u td
输入参数传递给函数来执行函数/闭包。感谢您的解释。我只是混淆了\u td
和td
naming.看起来,我可以使用td
是的,如果能得到一些关于td是什么以及td是什么的解释,那就太好了最后是。@Hermanningjaldson np,\u td
只是构成闭包的函数的输入参数,td
最后是传递给函数的值。它们实际上不必有不同的名称,例如,它们都可以是td
。希望有帮助:-)很好的解决方案,一切正常
for (var t=1;t<8;t++){
bind_event(t);
}
function bind_event(t) {
var td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(td);
});
}
}