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
相关产品推荐
相关产品推荐

