JavaScript循环变量注册DOM事件之强大的闭包
前言
在 JavaScript 中,我们经常使用循环语句(如 for
, while
, do-while
)来遍历数组、对象等集合类型的数据。在循环过程中,我们可能需要为集合中的每个元素注册某个 DOM 事件,如点击、鼠标悬浮等,为了实现这一目标,我们往往需要使用闭包的技巧。
闭包
在 JavaScript 中,闭包是指能够访问其他函数作用域内变量的函数。这是一种非常强大的编程技巧,在循环中注册 DOM 事件时也非常常用。
闭包的原理是:内部函数可以访问外部函数的变量,即便外部函数已经执行完毕,内部函数依然可以访问外部函数的变量。在循环中,我们需要创建一个闭包函数,以便为循环体内的每个元素注册 DOM 事件。
下面是一个示例:
let buttons = document.getElementsByTagName('button');
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
console.log(i);
});
}
上述代码会注册多个点击事件,每当点击某个 button
元素时,会在控制台输出 i
的值,但是这个值永远是循环结束后的最终值,而不是当前值。
为了解决这个问题,我们需要在循环内部创建一个闭包函数,并将当前 i
的值传递给它:
let buttons = document.getElementsByTagName('button');
for (let i = 0; i < buttons.length; i++) {
(function(index){
buttons[index].addEventListener('click', function() {
console.log(index);
});
})(i);
}
在上述代码中,我们使用了立即调用函数表达式(Immediately-Invoked Function Expression,IIFE),将当前的 i
变量作为参数传递给闭包函数,使得每个闭包函数都拥有了独立的 i
值。
示例说明
示例一
下面是一个简单的示例,展示了如何使用闭包来为列表元素添加点击事件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>闭包示例一:为列表元素添加点击事件</title>
</head>
<body>
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
</ul>
<script>
let items = document.getElementsByTagName('li');
for (let i = 0; i < items.length; i++) {
(function(index){
items[index].addEventListener('click', function() {
alert(items[index].textContent);
});
})(i);
}
</script>
</body>
</html>
在上述示例中,我们为列表元素添加了点击事件,当用户点击某个列表元素时,弹出一个对话框,显示该元素的文本内容。
示例二
下面是一个稍微复杂一些的示例,展示了如何使用闭包来为表格的表头和单元格添加点击事件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>闭包示例二:为表格的表头和单元格添加点击事件</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
}
th {
background-color: #eee;
}
td {
background-color: #fff;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
</tr>
</thead>
<tbody>
<tr>
<td>小明</td>
<td>18</td>
<td>男</td>
</tr>
<tr>
<td>小红</td>
<td>20</td>
<td>女</td>
</tr>
<tr>
<td>小李</td>
<td>22</td>
<td>男</td>
</tr>
</tbody>
</table>
<script>
let table = document.getElementsByTagName('table')[0];
let rows = table.rows;
let ths = rows[0].cells;
for (let i = 0; i < ths.length; i++) {
(function(index){
ths[index].addEventListener('click', function() {
alert(ths[index].textContent);
});
})(i);
}
for (let i = 0; i < rows.length; i++) {
let tds = rows[i].cells;
for (let j = 0; j < tds.length; j++) {
(function(row, col) {
tds[col].addEventListener('click', function() {
alert(rows[row].cells[col].textContent);
});
})(i, j);
}
}
</script>
</body>
</html>
在上述示例中,我们为表格的表头和单元格添加了点击事件。当用户点击表头或单元格时,弹出一个对话框,显示对应的文本内容。在循环中,我们使用了两级闭包,确保每个闭包函数都拥有了独立的行和列值。
总结
在循环中注册 DOM 事件时,一定要注意闭包的使用,否则会出现意想不到的问题。使用闭包,可以让每个循环体内的 DOM 元素都拥有独立的事件处理程序。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:javascript循环变量注册dom事件 之强大的闭包 - Python技术站