简体   繁体   English

数组将最后一个元素设为未定义

[英]Array gives last element as undefined

I am trying to write a function that deletes items from an array and you can undo the deletion by the undo function.我正在尝试编写一个 function 从数组中删除项目,您可以通过撤消 function 撤消删除。 If you pass an argument into the undo function starting with 0 as the first item and you pass 2 ( as 3 items) it returns undefined for the last item and I dont know why does it happen.如果您将参数传递给撤消 function 以 0 作为第一项开始并且您传递 2(作为 3 项)它返回未定义的最后一项,我不知道为什么会发生这种情况。 I tried tweaking the undo function and sometimes it returnd empty place in array and even empty x2.我尝试调整撤消 function,有时它会返回数组中的空位置,甚至是空 x2。

Can someone please explain why does that happen?有人可以解释为什么会这样吗?

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)
    }

};

Here is my html:这是我的 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>

Using splice inside a loop can often lead to undesired results: as you reduce the size of the array by it, but increase the loop variable, you have two problems:在循环中使用splice通常会导致不希望的结果:当您通过它减小数组的大小,但增加循环变量时,您会遇到两个问题:

  1. You'll skip elements: splice moves values to the left, in order to fill the gap of the deleted value.您将跳过元素: splice将值向左移动,以填补已删除值的空白。 But you still increase j in the next iteration, so one value slips through the mazes...但是你仍然会在下一次迭代中增加j ,所以一个值会从迷宫中溜走……

  2. As the array gets shorter and shorter, eventually j will point to an index that would have existed if you hadn't shortened the array, but now that it is shorter, it points beyond the end of the array, hence the undefined value.随着数组越来越短,最终j将指向一个索引,如果您没有缩短数组,该索引存在,但现在它更短了,它指向数组末尾之外,因此是undefined的值。

The solution is to not use splice within the loop, but only once after the loop, where it can remove all the iterated values in one go:解决方案是不在循环内使用splice ,而在循环只使用一次,它可以删除一个 go 中的所有迭代值:

        for(let j = 0; j <= undo; j++){
            testLista[testLista.length] = testUndo[j];
            console.log('Undo() - ', testUndo);
        }
        testUndo.splice(0, undo+1);

I should note that it is a bit unconventional to define undo as the last index to remove.我应该注意到,将undo定义为要删除的最后一个索引有点不合常规。 It would make more sense to define undo as the count of items to remove.undo定义为要删除的项目会更有意义。

Also, why not use testLista.push ?另外,为什么不使用testLista.push

Then you would have:然后你会有:

        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`

And using spread syntax, you can even get rid of the loop (still using the more logical definition of undo ):并且使用扩展语法,您甚至可以摆脱循环(仍然使用更合乎逻辑的undo定义):

        testLista.push(...testUndo.splice(0, undo));

Another example:另一个例子:

 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>

The problem is due to testUndo.splice(j, 1);问题是由于testUndo.splice(j, 1); in your undo function.在您的undo function 中。

The splice() method adds/removes items to/from an array at given index, and returns the removed item(s). splice()方法在给定索引的数组中添加/删除项目,并返回删除的项目。

Note : This method changes the original array.注意:此方法更改原始数组。

You are iterating over j and upto j<2 ;您正在迭代j直到j<2

for j=0 | testUndo = ["Sun", "Saturn", "Mars"]

spice will delete item at index 0 ie testUndo = ["Saturn", "Mars"] spice 将删除索引0处的项目,即testUndo = ["Saturn", "Mars"]

`for j=1 | testUndo = ["Saturn", "Mars"]`

spice will delete item at index 1 ie testUndo = ["Saturn"] spice 将删除索引1处的项目,即testUndo = ["Saturn"]

for j=2 | testUndo = ["Saturn"] for j=2 | testUndo = ["Saturn"] now there is no item at the index at 2, hence it will not delete anything. for j=2 | testUndo = ["Saturn"]现在索引 2 处没有项目,因此它不会删除任何内容。

Solution - you should splice at array at index 0解决方案 - 您应该在索引 0 处拼接数组

for(let j = 0; j <= undo; j++){
            testLista[testLista.length] = testUndo[0];
            testUndo.splice(0, 1);
            console.log('Undo() - ', testUndo);
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM