Javascript 为什么设置超时();功能不能像我想的那样工作?

Javascript 为什么设置超时();功能不能像我想的那样工作?,javascript,jquery,settimeout,Javascript,Jquery,Settimeout,我想做一个匹配的卡类游戏,并在点击后一次显示2张卡。如果它们相同,它们将变得不活动,如果它们不相同,它们将再次被覆盖 这是一个实现,在点击后1.5秒打开卡片 $(document).on("click", "div.card.covered", function(){ if( $('div.card.uncovered').length < 2 ){ uncover_card(this); } if( $('div.card.u

我想做一个匹配的卡类游戏,并在点击后一次显示2张卡。如果它们相同,它们将变得不活动,如果它们不相同,它们将再次被覆盖

这是一个实现,在点击后1.5秒打开卡片

$(document).on("click", "div.card.covered", function(){    
    if( $('div.card.uncovered').length < 2 ){
        uncover_card(this);
    }       
    if( $('div.card.uncovered').length == 2 ){
        var uncovered_cards = new Array();          
        $('div.card.uncovered').each(function(){
            uncovered_cards.push( $(this).attr("class") );
        });

        if( uncovered_cards[0] == uncovered_cards[1]){
            setTimeout(function(){
                $('div.card.uncovered').addClass("matched");
                $('div.card.uncovered').removeClass("uncovered");
                //uncover_card(this);
            },1000);                
        }else{
            setTimeout(function(){
                $('div.card.uncovered').addClass("covered");
                $('div.card.uncovered').removeClass("uncovered");
                //uncover_card(this);
            },1000);
        }
    }
});
$(文档)。在(“单击”,“div.card.covered”,function(){
if($('div.card.uncovered')。长度<2){
揭开卡(本);
}       
如果($('div.card.uncovered')。长度==2){
var\u cards=新阵列();
$('div.card.uncovered')。每个(函数(){
未覆盖的卡。推送($(this.attr(“类”));
});
如果(未覆盖的\u卡[0]==未覆盖的\u卡[1]){
setTimeout(函数(){
$('div.card.uncovered').addClass(“匹配”);
$('div.card.uncovered').removeClass(“uncovered”);
//揭开卡(本);
},1000);                
}否则{
setTimeout(函数(){
$('div.card.uncovered').addClass(“covered”);
$('div.card.uncovered').removeClass(“uncovered”);
//揭开卡(本);
},1000);
}
}
});

如果你慢慢地做,它会像预期的那样工作

但是,如果你点击2,然后疯狂地点击第三张卡,同时等待它们变为非活动或再次掩盖,这第三张卡将在这对卡被更改后不久,也会更改为与这对卡相同的状态


为什么会发生这种错误

之所以发生这种情况,是因为您正在将类“matched”添加到与div.card.selector匹配的每一张卡中。这将包括同时点击的任何卡片。如果缓存了第一次选择的“未覆盖”元素,那么只要匹配成功,就可以对它们进行操作。下面是一个工作片段:

    var uncovered_cards = [];
    var els = $('div.card.uncovered');
    els.each(function(){
        uncovered_cards.push( $(this).attr("class") );
    });

    if( uncovered_cards[0] == uncovered_cards[1]){
        setTimeout(function(){
            els.addClass("matched");
            els.removeClass("uncovered");
            //uncover_card(this);
        },1000);            
    }

这里的问题在于
setTimeout
函数

基本上,在超时间隔结束时,您将查找所有具有
未覆盖的
类的卡,并覆盖它们或匹配它们。通过点击第三张卡“像疯了一样”,您可以将第三张卡设置为
uncovered
,然后
setTimeout
可以查询
$('div.card.uncovered')
,从而匹配/覆盖所有
uncovered

解决方案是通过引用匹配/覆盖两张卡,而不是在超时结束时再次查询它们

大概是这样的:

setTimeout(function(){
    uncovered_cards[0].addClass("matched");
    uncovered_cards[0].removeClass("uncovered");

    uncovered_cards[1].addClass("matched");
    uncovered_cards[1].removeClass("uncovered");
},1000);

请注意:我没有测试上述代码,它可能无法正常工作。它只是用来演示这个概念。

正如@KevinB在评论中提到的,问题是每次单击都会添加一个额外的超时。当第一次超时触发时,它将从两张卡中删除
未覆盖的
类。现在,因为你快速点击,你发现了另一张牌。但是,您的第二次(或第三次、第四次等)超时会触发并作用于任何未覆盖的卡,从而影响此新未覆盖的卡

最简单的解决方法是将第二个
if
移动到第一个
的内部,这样它只会触发一次

if( $('div.card.uncovered').length < 2 )
{
    uncover_card(this);

    if( $('div.card.uncovered').length == 2 )
    {
        var uncovered_cards = new Array();

        $('div.card.uncovered').each(function(){
            uncovered_cards.push( $(this).attr("class") );
        });

        if( uncovered_cards[0] == uncovered_cards[1])
        {
            setTimeout(function(){
                $('div.card.uncovered').addClass("matched");
                $('div.card.uncovered').removeClass("uncovered");
                //uncover_card(this);
            },1000);

        }
        else
        {
            setTimeout(function(){
                $('div.card.uncovered').addClass("covered");
                $('div.card.uncovered').removeClass("uncovered");
                //uncover_card(this);
            },1000);
        }
    }
}
if($('div.card.uncovered')。长度<2)
{
揭开卡(本);
如果($('div.card.uncovered')。长度==2)
{
var\u cards=新阵列();
$('div.card.uncovered')。每个(函数(){
未覆盖的卡。推送($(this.attr(“类”));
});
如果(未覆盖的\u卡[0]==未覆盖的\u卡[1])
{
setTimeout(函数(){
$('div.card.uncovered').addClass(“匹配”);
$('div.card.uncovered').removeClass(“uncovered”);
//揭开卡(本);
},1000);
}
其他的
{
setTimeout(函数(){
$('div.card.uncovered').addClass(“covered”);
$('div.card.uncovered').removeClass(“uncovered”);
//揭开卡(本);
},1000);
}
}
}

因为。。。每次单击都会启动一个新的超时?