0

I have two nested for loops; basically what I'm trying to do is inserting some rows inside an array that contains lines of text;

I look for the placeholder

'// <<<PERMISSIONS TREE>>>'

and insert some lines just after it; before doing this, I check if some lines are already there after the above placeholder and before

'// <<<END PERMISSIONS TREE>>>'

In this case I need first to delete these rows and then insert the new ones

for(i = 0; i < lines.length; i++) {
    if (lines[i].indexOf('// <<<PERMISSIONS TREE>>>') >= 0) {

        i++;
        var j = i;
        console.log(lines[j]);      //here lines[j] is defined and printed on screen correctly
        console.log(lines[j].indexOf('// <<<END PERMISSIONS TREE>>>'));    //this also works

        //start delete loop - the following line doesn't work
        while ((lines[j].indexOf('// <<<END PERMISSIONS TREE>>>') < 0) && (j < lines.length)) {
            lines.splice(j, 1);
            j++;
        }

        lines.splice(i , 0, result);  // insert result in the correct place, this works
        break;
    }
}

In the line where I start the while loop, I get the error:

Cannot call method 'indexOf' of undefined

but the two lines above (the logs) works; I just can't understand why...

This code runs in nodejs, don't know if this does matter;

3
  • What about when i is equal to lines.length - 1, and then you increment it by 1, and try to look at lines[j] after that? Commented Oct 16, 2014 at 2:43
  • Also in that while loop you check .indexOf() before you check to see if j is in range! Commented Oct 16, 2014 at 2:44
  • Then the value is not "defined". The JS engine is right. You are wrong. Correct/update the assertion (and title). What's the problem? Use a debugger as necessary. Commented Oct 16, 2014 at 3:20

2 Answers 2

6

When you splice, you remove an element from the array, and shift the index of each element after it down by one. If you then increment your index j, you're committing an off-by-one error.

arr = [1, 2, 3];
arr[1]; // 2
arr.splice(1, 1); // arr is now [1, 3]
arr[1]; // 3
arr.splice(1, 1); // arr is now [1]
arr[1]; // undefined

You can avoid this by just not incrementing j, since it's now referring to a new element of the array, which is what you want.

Sign up to request clarification or add additional context in comments.

2 Comments

That's correct! I was going out of range with index
Also the Amadan suggestion is useful, since checking the index against the array length BEFORE checking the rest, avoid everything to crash if the second placeholder is missing for some reason
3

Reverse the conditions as follows:

while ((j < lines.length) && (lines[j].indexOf('// <<<END PERMISSIONS TREE>>>') < 0)) {

The reason for the error is the fact that you first try to use lines[j], and only after check whether j is legal.

There may also be an unrelated logic error as Chris Hayes describes. Note that even without incrementing j, if the string block is not terminated, you would run into the same error.

1 Comment

Good catch. I've been bitten by splice so many times that I didn't even consider this part.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.