Javascript-onClick事件向函数传递相同的参数

Javascript-onClick事件向函数传递相同的参数,javascript,html,Javascript,Html,我迭代容器中的元素,并向每个元素添加onClick。我希望执行一个方法,当我点击一个元素时,它接受一个id作为参数。id对于每个元素都是唯一的 下面是我的代码: $(document).ready(function() { var conElement = document.getElementById("my-container"); if (conElement) { var bookElements = conElement.getElements

我迭代容器中的元素,并向每个元素添加onClick。我希望执行一个方法,当我点击一个元素时,它接受一个id作为参数。id对于每个元素都是唯一的

下面是我的代码:

$(document).ready(function() 
{
    var conElement = document.getElementById("my-container");
    if (conElement)
    {
        var bookElements = conElement.getElementsByClassName("book-elements");

        for (var element = bookElements.length; element--; )
        {
            var bookElement = bookElements[element];
            var bookId = bookElement.getAttribute('book-id');

            alert ('Book id is ' + bookId);
            bookElement.onclick = function() {showBookSummary(bookId)};
        }
    }

});

function showBookSummary(bookId)
{
    alert ('Book id inside showBookSummary is ' + bookId);
}
问题:每次单击任何元素时都会传递相同的图书id。假设我有3个元素,第一个元素的id是“123”,第二个元素是“456”,第三个元素是“789”。每当我点击这3个元素中的任何一个,它总是将id“123”作为bookId传递给showBookSummary函数


我这里漏了什么吗?

问题

您的问题是因为
bookId
是一个保留其值的常规JS变量。不是保存该书的
bookId
,而是运行代码后的bookId

代码执行如下所示:

bookId = 789 (id of first book because you are starting at top and decrementing)
bookId = 456 (second element)
bookId = 123 (third element)
然后
bookId
仍然是123,因为您仍然在使用
bookId
变量。因此,无论何时您致电:

showBookSummary(bookId);
bookId
仍然是123


解决方案

相反,我认为你应该改变思路:

bookElement.onclick = function() {showBookSummary(bookId)};
致:

编辑:onclick处理程序根据注释将积分添加到@RobG。是的,我现在意识到把它当作一根弦是行不通的。这是通过将
bookId
替换为
t
实现的,基本上存储正确的
bookId
,而不是使用在执行过程中更改的变量

编辑:可能更简单的解决方案

根据另一个SO答案(标记为duplicate),相对较新的
let
关键字似乎在这方面也有帮助。它创建了循环范围的局部变量,而不是函数。因此,如果您只是更改
bookId
的声明:

var bookId = ...

let bookId = ...
这也应该起作用。我还没试过,但看起来很有希望


另一方面,如果您使用的是jQuery,则可以替换可怕的:

document.getElementById("id")
document.getElementsByClassName("class")
for(var element = bookElements.length; element--; )
getAttribute("attr")
element.onclick = function()
使用jQuery内置的速记:

$("#id")
$(".class")
elements.each(
attr("attr")
elements.click(function()

不,不要那样做。OP应该使用以下内容来打破闭包:
…onclick=(函数(t){return function(){showBookSummary(t)})(bookId)
@RobG为什么不这样做?处理函数的好处是什么?@Jonathan-如果我使用“function(){showBookSummary(+bookId+”);作为字符串,我的单击事件根本不起作用。当我单击元素时,什么都不会发生。函数()是否也应该在双引号内?它的效果非常好。只是在解决方案中缺少一个结尾“}”。Final-“(函数(t){return function(){showBookSummary(t);};})(bookId);”谢谢@Jonathan和@RobG!!
$("#id")
$(".class")
elements.each(
attr("attr")
elements.click(function()