为何为元素分配颜色时最后一个元素出现undefined?
问题原因分析
最后一个元素出现undefined的核心原因是硬编码索引值 + 数组被多次修改导致索引越界:
- 获取
currentColor时使用了固定计算式(8 - 1) - indexColor,但每次循环都会从shuffledArray中删除元素,数组长度持续减少,当循环到最后一次(indexColor=8),计算出的索引会超出数组剩余元素的范围,返回undefined。 remove_item函数逻辑混乱,修改数组副本后未正确传递结果,同时直接操作全局shuffledArray,导致数组状态混乱。
修复方案
重新梳理逻辑:先收集所有颜色,为每个元素生成排除自身颜色的可用列表,再通过洗牌和匹配确保颜色不重复且符合要求:
// 获取所有元素 const rows = document.querySelectorAll('.row'); // 收集所有颜色 const colors = Array.from(rows).map(row => row.classList[1]); // Fisher-Yates 标准洗牌函数 const shuffle = (array) => { const arr = [...array]; for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; }; // 生成排除自身颜色的可用颜色列表 const getAvailableColors = (selfColor) => { return shuffle(colors.filter(color => color !== selfColor)); }; // 为每个元素分配不重复的颜色 const assignedColors = new Set(); rows.forEach(row => { const selfColor = row.classList[1]; // 设置背景色 row.style.backgroundColor = selfColor; // 过滤出未被分配的可用颜色 const available = getAvailableColors(selfColor).filter(c => !assignedColors.has(c)); const selectedColor = available[0]; assignedColors.add(selectedColor); // 添加颜色文本 row.innerHTML = `<span style="color: ${selectedColor}">${selectedColor}</span>`; });
body { background-color: #eeeeee; display: flex; justify-content: center; flex-direction: column; } .con { display: flex; justify-content: space-between; width: 100%; } .row { margin: 20px; width: 150px; height: 150px; border-radius: 50%; display: flex; justify-content: center; align-items: center; } .row span { font-size: 23px; }
<div class="con"> <div class="row yellow"></div> <div class="row red"></div> <div class="row black"></div> </div> <div class="con"> <div class="row white"></div> <div class="row green"></div> <div class="row brown"></div> </div> <div class="con"> <div class="row lightpink"></div> <div class="row orange"></div> <div class="row orchid"></div> </div>
关键改进点
- 消除硬编码索引:通过动态过滤可用颜色,确保每次都能拿到有效颜色值,避免索引越界。
- 简化逻辑:用
Set跟踪已分配颜色,确保不重复;用filter直接排除自身颜色,替代复杂的splice操作。 - 标准洗牌实现:采用Fisher-Yates洗牌算法,逻辑清晰且高效。
内容的提问来源于stack exchange,提问作者Ricko Abbderahamne
相关产品推荐
相关产品推荐

