简体   繁体   中英

Splicing first object returns TypeError: Cannot read property of undefined

I have an array like this:

var arrSession = [ { name: 'Product 01', groupID: '50303', delivery: 'mail'}, { name: 'Product 02', groupID: '50403', delivery: 'bike'} ]

And this Loop to delete specific objects:

for(var i=0, len=arrSession.length; i<len; i++) {
    if (arrSession[i].groupID == getGroupID && arrSession[i].delivery == getDelivery) {
        arrSession.splice(i, 1);
    }
}

If I'm deleting the last object, all works fine:

var getGroupID = 50403;
var getDelivery = bike;

But if I'm deleting the first object:

var getGroupID = 50303;
var getDelivery = mail;

I get an error:

TypeError: Cannot read property 'groupID' of undefined  

Why so and how to solve it?

Edit:

If there is only one object all is fine too.

var arrSession = [ { name: 'Product 01', groupID: '50303', delivery: 'mail'} ]

I think this is because when the loop starts, it will go up to index 1. After you delete index 0, your loop will still try to run and search for index 1, the second object, which has already been moved. If you put a break keyword in the if statement, the error should be fixed.

for(var i=0, len=arrSession.length; i<len; i++) {
    if (arrSession[i].groupID == getGroupID && arrSession[i].delivery == getDelivery) {
        arrSession.splice(i, 1);
        break;
    }
}

Pretty simple, you iterate from the start of the array and you splice the array on found. The array is now shorter than the stored length and any access goes wrong.

You could loop from the end instead.

 var arrSession = [{ name: 'Product 01', groupID: '50303', delivery: 'mail' }, { name: 'Product 02', groupID: '50403', delivery: 'bike' }], getGroupID = 50303, getDelivery = 'mail', i = arrSession.length; while (i--) { if (arrSession[i].groupID == getGroupID && arrSession[i].delivery == getDelivery) { arrSession.splice(i, 1); } } console.log(arrSession);

Try it converting 'groupId' to integer format.

ex-:

for(var i=0, len=arrSession.length; i<len; i++) {
    if (parseInt(arrSession[i].groupID) == getGroupID && arrSession[i].delivery == getDelivery) {
        arrSession.splice(i, 1);
    }
}

Array.splice mutates the array. If you remove the first element, the array length decreases by 1 but in the loop it still tries to access the next element which may or may not be undefined . Here since there are only 2 elements the arrSession[1] is undefined .

Instead use filter like this:

 var arrSession = [{ name: 'Product 01', groupID: '50303', delivery: 'mail' }, { name: 'Product 02', groupID: '50403', delivery: 'bike' }] var getGroupID = 50303; var getDelivery = 'mail'; var filtered = arrSession.filter(session => session.id.== getGroupID && session.delivery !== getDelivery) console.log(filtered)

Hope this helps !

Short Answer : Due to the for loop syntax. Initialization happens only once . You missed to update len after splicing .

for ([initialExpression]; [condition]; [incrementExpression]) statement

Solution : As already mentioned in the other answers, you can break the loop (which will work if you are spicing only one item).

 const arrSessionActual = [{ name: 'Product 01', groupID: '50303', delivery: 'mail' }, { name: 'Product 02', groupID: '50403', delivery: 'bike' }]; function removeItem(arrSession, getGroupID, getDelivery) { for (var i = 0, len = arrSession.length; i < len; i++) { if (arrSession[i].groupID == getGroupID && arrSession[i].delivery == getDelivery) { arrSession.splice(i, 1); len = arrSession.length; // This is missing } } console.log(arrSession); } removeItem(arrSessionActual.slice(), 50403, 'bike'); removeItem(arrSessionActual.slice(), 50303, 'mail');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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