You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中数组元素互移遇问题,求教splice()与indexOf()参数用法

卡牌数组转移异常问题排查与修复

问题描述

首次使用JavaScript的splice()和indexOf()方法开发卡牌游戏时遇到异常:点击卡牌切换状态并在upcards和downcards数组间转移,但卡牌从upcards移回downcards后,upcards仍保留该元素,还莫名存入了pcard2。

原代码如下:

var statusc1 = 'down';
let upcards = [];
let downcards = [
    pcard1,
    pcard2,
    pcard3,
    pcard4,
    pcard5
];


pcard1.addEventListener('click', ()=> {
    if(statusc1 == 'down') {
        console.log('its down');
        pcard1.style.bottom = -10;
        statusc1 = 'up';

        upcards.push(downcards[0]);
        downcards.splice(downcards.indexOf(pcard1),1);
        console.log(upcards);
    } else {
        console.log('its up');
        pcard1.style.bottom = -60;
        statusc1 = 'down';

        downcards.push(upcards[0]);
        upcards.splice(downcards.indexOf(pcard1),1);
        console.log(downcards);
    }
})

问题原因分析

  • 元素转移逻辑错误:转移时用upcards.push(downcards[0])和downcards.push(upcards[0]),取的是数组第一个元素而非当前点击的pcard1。如果downcards第一个元素是pcard2,就会错误把pcard2推入upcards,这就是莫名出现pcard2的原因。
  • splice索引使用错误:从upcards删除元素时,用了downcards.indexOf(pcard1)获取索引——此时pcard1已经被推入downcards,拿到的是它在downcards里的索引,而非upcards中的索引。如果这个索引超出upcards的长度,splice()不会执行删除操作,导致upcards保留元素。

核心方法参数说明

  • indexOf(element):返回元素在数组中的第一个匹配索引,找不到则返回-1,必须在目标数组上调用才能拿到正确索引。
  • splice(startIndex, deleteCount):从startIndex位置开始,删除deleteCount个元素。如果startIndex超出数组范围,不会执行删除。

修正后的代码

var statusc1 = 'down';
let upcards = [];
let downcards = [
    pcard1,
    pcard2,
    pcard3,
    pcard4,
    pcard5
];


pcard1.addEventListener('click', ()=> {
    if(statusc1 == 'down') {
        console.log('its down');
        pcard1.style.bottom = -10;
        statusc1 = 'up';

        // 直接推入当前点击的pcard1,而非数组第一个元素
        upcards.push(pcard1);
        // 在downcards中找到pcard1的索引并删除
        downcards.splice(downcards.indexOf(pcard1), 1);
        console.log(upcards);
    } else {
        console.log('its up');
        pcard1.style.bottom = -60;
        statusc1 = 'down';

        // 直接推入当前点击的pcard1
        downcards.push(pcard1);
        // 在upcards中找到pcard1的索引并删除
        upcards.splice(upcards.indexOf(pcard1), 1);
        console.log(downcards);
    }
})

额外优化建议

可以把状态变量和事件监听逻辑封装成通用函数,避免为每张卡牌写重复代码:

function setupCard(card) {
    let status = 'down';
    card.addEventListener('click', () => {
        if (status === 'down') {
            card.style.bottom = -10;
            status = 'up';
            upcards.push(card);
            downcards.splice(downcards.indexOf(card), 1);
        } else {
            card.style.bottom = -60;
            status = 'down';
            downcards.push(card);
            upcards.splice(upcards.indexOf(card), 1);
        }
        console.log('upcards:', upcards, 'downcards:', downcards);
    });
}

// 为所有卡牌绑定事件
setupCard(pcard1);
setupCard(pcard2);
setupCard(pcard3);
setupCard(pcard4);
setupCard(pcard5);

内容的提问来源于stack exchange,提问作者GrimmTVT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:55:38