javascript - 为什么我的计数器每次都会增加多个?

标签 javascript jquery

我正在使用 jQuery 创建一个测试,但无法弄清楚为什么当使用正确答案时,我的计数器变量 count 似乎增加了不止一。

function nextQuestion(){
    $('#submit').show();
    $('#next').hide();
    $('#result').text('');
    $('#value').val('');
    randomNumber = Math.floor((Math.random() * words.length));
    $('#englishWord').text(words[randomNumber][0]);
    $('#submit').click(function(){
        if ($('#value').val() == words[randomNumber][1])
        {
            $('#result').text("You are correct, well done");
            $('#submit').hide();
            $('#next').show();

            $('#next').click(function(){
                count = count + 1;
                $('#score').text(count); 
                nextQuestion();              
            });
        }
        else 
        {
            $('#result').text("That is incorrect, try again");
            count = 0;
            $('#score').text(count);
        }
    });
}

最佳答案

count每次点击 #next 都会增加超过 1因为您要向 click 添加多个匿名监听器事件#next元素。这些函数中的每一个都独立地添加 1count 。因此,当 #next单击,count对于您添加到 click 的每个匿名监听器,都会增加 1事件于 #next元素。

每次点击#submit$('#value').val() == words[randomNumber][1]你执行:

$('#next').click(function(){
    count = count + 1;
    $('#score').text(count); 
    nextQuestion();              
});

这会导致一个新的匿名函数作为监听器添加到 #next元素的click事件以及任何已经监听该事件的事件。因此,每次都有 click事件于 #next调用了多个函数,每个函数都会增加 count减1.每次点击增加的总金额#next取决于您有多少个函数正在监听该事件。

您对 click 也有同样的问题事件#submit元素。这会导致count通过向 click 添加更多听众来进一步增加事件#next元素。第一次#submit单击将添加一个监听器。上二#submit单击 #submit 的两个监听器click每个事件都会向 #next 添加另一个监听器click事件使得该事件共有 3 个监听器。因此,count增加 3。随着您向每个事件添加越来越多的监听器,该值会继续扩大。

让您的代码仅添加事件监听器一次

解决此问题的方法是仅分配这些点击事件一次:

$('#submit').click(function(){
    if ($('#value').val() == words[randomNumber][1])
    {
        $('#result').text("You are correct, well done");
        $('#submit').hide();
        $('#next').show();
    }
    else 
    {
        $('#result').text("That is incorrect, try again");
        count = 0;
        $('#score').text(count);
    }
});

$('#next').click(function(){
    count = count + 1;
    $('#score').text(count); 
    nextQuestion();              
});

function nextQuestion(){
     $('#submit').show();
     $('#next').hide();
     $('#result').text('');
     $('#value').val('');
     randomNumber = Math.floor((Math.random() * words.length));
     $('#englishWord').text(words[randomNumber][0]);
}

或者,使用命名函数并依赖 addEventListener() 忽略您添加相同监听器的尝试。

另一种解决方案是使用单个命名函数,该函数在一个范围内定义,这样每次调用添加它的代码时就不会重新定义它。未使用 event attributes 添加的监听器(例如 <div onclick="doSomething();"> )使用 addEventListener() 添加(jQuery 在它提供的用于添加事件监听器的各种方法中使用此方法)。如果您尝试添加相同的功能,请对其他参数使用相同的值 addEventListener() ,然后 additional listeners are discarded 。这意味着即使您尝试多次添加具有相同参数的相同函数,每个事件也只会调用一次。对于匿名函数,每次运行代码时都会单独定义该函数。因此,虽然代码相同,但定义的函数与代码运行之前的任何时间都是分开的。结果,添加了多个副本。

但是,仅仅因为该函数有一个名称并不意味着它是在一个范围内定义的,这将导致每次添加它时不会重新定义它。例如,在上面的代码中,如果函数为#next监听器是在 #submit 中定义的监听器,即使它有一个名称,每次 #submit 仍然会重新定义它。监听器已运行。要防止函数被重新定义,关键在于函数的定义方式和位置,而不仅仅是它是一个命名函数。但是,为了引用该函数,它必须有一个名称,或者以其他方式与变量关联。因此,您通常会发现,当有人说“命名函数”时,会做出一个假设,即它的定义方式通常不会重新定义。

关于javascript - 为什么我的计数器每次都会增加多个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38808272/

相关文章:

javascript - CSS 的点击功能

javascript - 如何在 Internet Explorer 的新选项卡中打开网页?

javascript - 如何显示谷歌字体预览

javascript - 合并事件监听器

javascript - 带有 templateUrl 和 ng-repeat 的自定义指令

javascript - jQuery 在单选按钮上切换背景颜色

javascript - 我如何仅通过其可观察属性的变化来了解 knockout.js ViewModel 的变化?

Javascript 递归调用会产生范围错误

javascript - "npm run build"如何运行 jquery github 存储库中的脚本?

javascript - el-table 中的自定义列标题没有反应