也许是一个愚蠢的问题,但我刚刚开始学习JS。
如何使用以下代码(例如)记录单击了哪个表格单元格。
// Get array of td elements; 9 cells for game board
var board = document.getElementsByTagName("td");
for (var i = 0; i < board.length; i++) {
console.log(board[i]);
board[i].addEventListener("click", function() {
console.log(board[i]);
console.log(i);
});
}
&#13;
<!DOCTYPE html>
<html>
<body>
<table border="1">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
</body>
</html>
&#13;
登录董事会[i]或[i]不工作;我总是出现9,而且[i]未定义。
编辑:做一些挖掘,我设法偶然发现了一些东西并把它们放在一起使它们起作用。
但是,我仍然没有真正理解它是如何运作的。function testf(i) {
return (function(){
console.log("you clicked region number " + i);
});
}
// Trigger function cellClicked() when any table cell is clicekd
for (var i = 0; i < board.length; i++) {
board[i].addEventListener("click", testf(i));
}
答案 0 :(得分:1)
您误解的是语句变量i
是块作用域的。但是在JavaScript中用var
初始化的变量是函数作用域。因此,在事件被触发时,变量i
为9
,因为循环已完成。
使用ES2015,您可以将var
替换为let
并完成,因为let
使用块范围初始化变量:
for (let i = 0; i < board.length; i++) {
console.log(board[i]);
board[i].addEventListener("click", function() {
console.log(board[i]);
console.log(i);
});
}
但这仅适用于新浏览器,或者当您使用babel将代码转换为ES5时。
您必须为i
引入新的范围,以便为每次迭代保留i
的值,以使其在没有let
function handleClick(i) {
// function sets new scope for i
return function() {
console.log(board[i]);
console.log(i);
}
}
for (let i = 0; i < board.length; i++) {
console.log(board[i]);
board[i].addEventListener("click", handleClick(i));
}
答案 1 :(得分:0)
只是不要在点击内使用i变量并将其替换为此。正如你在这里看到的那样 -
board[i].addEventListener("click", function() {
console.log(this);
console.log(this.innerHTML);
});
答案 2 :(得分:0)
您可以将事件注入函数以获取对事件的目标(在本例中为td元素)的引用,然后获取innerText或innerHtml,如下所示:
board[i].addEventListener("click", function(event) {
console.log(event.target.innerText);
});
答案 3 :(得分:0)
首先,将您的函数移出循环以保存多次重新创建相同的函数。然后,在函数内部,只需使用this
关键字来访问被点击的元素:
function log(){
// this is passed from the EventTarget.addEventListener()
// method:
console.log(this, this.textContent);
}
// Get array of td elements; 9 cells for game board
var board = document.getElementsByTagName("td");
for (var i = 0; i < board.length; i++) {
board[i].addEventListener("click", log);
}
&#13;
<table border="1">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
&#13;
或者,您可以将事件处理委托给祖先<table>
元素:
function log(e){
// this is passed from the EventTarget.addEventListener()
// method, but here refers to the <table> element, to find
// the clicked <td> element we need to look at the
// target property of the 'event' (here 'e') also passed
// from the addEventListener() method:
console.log(this, e.target, e.target.textContent);
}
// retrieving the first/only <table> element on the page,
// adding the event-listener for the click-event and
// binding the log() function as the event-handler:
var board = document.querySelector('table').addEventListener('click', log);
&#13;
<table border="1">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
&#13;
答案 4 :(得分:0)
这是众所周知的错误。
在循环中创建闭包:一个常见的错误 见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
这可以解决您的问题
window.onload = function () {
function logEvent(a, b) {//closure function
return function () {
console.log(a);//values from outer function
console.log(b);
}
}
var board = document.getElementsByTagName("td");
for (var i = 0; i < board.length; i++) {
console.log(board[i]);
var log = logEvent(board[i].innerHTML, i);//take values when they exist
board[i].addEventListener("click", log);
//board[i].addEventListener("click", logEvent(board[i].innerHTML, i));//this way is also possible
}
}