我正在尝试编写一个函数,该函数从数组中删除项,您可以通过undo函数撤消删除。如果您将一个参数传递给undo函数,以0作为第一项,然后传递2(作为3项),则返回最后一项未定义的参数,我不知道为什么会发生这种情况。我试着调整撤销函数,有时它会返回数组中的空位置,甚至是空的x2。
有人能解释一下为什么会发生这种事吗?
let testLista = ['Mars', 'Jupiter', 'Saturn', 'Sun'];
let testUndo = [];
let i = 0;
const delItem = del => {
let indexOfDel = testLista.indexOf(del);
if(testLista.includes(del)){
testLista.splice(indexOfDel, 1);
document.write(`<h3>Deleted: <em>${del}</em></h3>`)
testUndo[i] = del;
console.log('delItem() undo - ',testUndo);
console.log('delItem() list - ',testLista);
i++;
}else{
document.write(`<h2>That item does not exist! Available items: <em>${testLista.join(', ')}</em></h2>`);
}
}
delItem('Sun');
delItem('Saturn');
delItem('Mars');
const undoFunc = (undo) => {
if(undo >= 1 && undo < testUndo.length){
for(let j = 0; j <= undo; j++){
testLista[testLista.length] = testUndo[j];
testUndo.splice(j, 1);
console.log('Undo() - ', testUndo);
}
}else{
testLista[testLista.length] = testUndo[testUndo.length-1];
console.log('Undo() - ', testLista)
}
};这是我的html:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="main.js"></script>
</body>
</html>发布于 2020-07-19 15:56:03
这个问题是由于您的testUndo.splice(j, 1);函数中的undo。
splice()方法在给定索引处将项添加/移除到数组中,并返回删除的项。
Note__:此方法更改原始数组。
您正在迭代j和向上的j<2;
for j=0 | testUndo = ["Sun", "Saturn", "Mars"]spice将删除索引 i.e testUndo = ["Saturn", "Mars"]中的项。
`for j=1 | testUndo = ["Saturn", "Mars"]`spice将删除索引1 i.e testUndo = ["Saturn"]中的项
for j=2 | testUndo = ["Saturn"]现在在索引2处没有项目,因此它不会删除任何东西。
解决方案-您应该在索引0的数组中拼接。
for(let j = 0; j <= undo; j++){
testLista[testLista.length] = testUndo[0];
testUndo.splice(0, 1);
console.log('Undo() - ', testUndo);
}发布于 2020-07-19 16:11:34
在循环中使用splice通常会导致不希望得到的结果:当您通过它缩小数组的大小,但增加循环变量时,您会遇到两个问题:
splice向左移动值,以填补已删除值的空白。但是在下一次迭代中仍然会增加j,因此有一个值从迷宫中滑过.当数组变得越来越短时,
undefined值。解决方案是不在循环中使用splice,而只在循环之后使用一次,在循环之后,它可以一次删除所有迭代值:
for(let j = 0; j <= undo; j++){
testLista[testLista.length] = testUndo[j];
console.log('Undo() - ', testUndo);
}
testUndo.splice(0, undo+1);我应该注意,将undo定义为要删除的最后一个索引有点不合常规。将undo定义为要删除的项的计数将更有意义。
另外,为什么不使用testLista.push呢?
那你就会:
for(let j = 0; j < undo; j++) { // now `undo` is a count!
testLista.push(testUndo[j]);
console.log('Undo() - ', testUndo);
}
testUndo.splice(0, undo); // no more `+1`使用spread语法,您甚至可以去掉循环(仍然使用更符合逻辑的undo定义):
testLista.push(...testUndo.splice(0, undo));发布于 2020-07-19 16:12:58
另一个例子是:
let planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Sun'];
let deletedPlanets = [];
const planetList = document.getElementById('planet-list');
const deletePlanet = (planet) => {
const ind = planets.indexOf(planet);
deletedPlanets.push({ind, planet});
planets.splice(ind, 1);
drawPlanetList();
};
const drawPlanetList = () => {
planetList.innerHTML = '';
planets.forEach((planet) => {
const div = document.createElement('div');
div.innerText = planet;
div.onclick = () => {
deletePlanet(planet);
};
planetList.appendChild(div);
});
}
const deleteMultiple = () => {
deletePlanet('Mars');
deletePlanet('Jupiter');
deletePlanet('Sun');
drawPlanetList();
}
const undo = () => {
if (!deletedPlanets.length) {
return ;
}
const undoObj = deletedPlanets.pop();
planets.splice(undoObj.ind, 0, undoObj.planet);
drawPlanetList();
}
drawPlanetList();div {
padding: 0.4em;
border-bottom: 1px inset gray;
}Clicking on list elements deletes them.
<button onclick="deleteMultiple()">
delete multiple
</button>
<button onclick="undo()">
undo
</button>
<section id="planet-list"></section>
https://stackoverflow.com/questions/62982094
复制相似问题