1

Sometimes the simplest things become the most confusing.

let arr = ['x', 'y', 'z'];

for(let i = 0; i <= arr.length; i++) {
    let prop = arr.shift();
    console.log(prop); 
    console.log(arr, `${i} <= ${arr.length}`);
}

it prints out

x
[ 'y', 'z' ] '0 <= 2'
y
[ 'z' ] '1 <= 1'

How come 'z' doesn't show up with this code as part of the console.log(prop)?

3
  • Because you're adjusting the length of the array with every shift. Commented Mar 6, 2019 at 16:18
  • by z, shouldn't the length be 1 with i being 1, 1 <= 1? Commented Mar 6, 2019 at 16:19
  • But by then i is 2. Commented Mar 6, 2019 at 16:25

6 Answers 6

4

You short the array by shifting and use an index with is incrementing for every loop.

The result is it loops only twice, one for element one and two, and one for element three.

At the end, you got index 2, but the length of the array is 1.

let arr = ['x', 'y', 'z'];

for(let i = 0; i <= arr.length; i++) {
    let prop = arr.shift();
    console.log(prop); 
    console.log(arr, `${i} <= ${arr.length}`);
}

A better approach by using only the shiftend element and checking only the length of the array.

let arr = ['x', 'y', 'z'],
    i = 0;

while (arr.length) {
    let prop = arr.shift();
    console.log(prop); 
    console.log(arr, `${++i} < ${arr.length}`);
}

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

Comments

2

You adjust the length of the array with every shift call, and the boundary check inside your for-loop tests against that.

You can cache the length in another variable to demonstrate:

let arr = ['x', 'y', 'z'];
let len = arr.length;

for(let i = 0; i < len; i++) {
    let prop = arr.shift();
    console.log(prop); 
    console.log(arr, `${i} <= ${arr.length}`);
}

This technique was once recommended by some for performance reasons; that is rarely necessary any more. But if your loop is changing the array, it might still be important.


Why this doesn't work as is:

  1. set arr to ['x', 'y', 'z']
  2. set i to 0
  3. test i <= arr.length, true since 0 <= 3
  4. do loop body, prop is 'x', arr is ['y', 'z']
  5. perform i++, now i is 1
  6. test i < arr.length, true since 1 <= 2
  7. do loop body, prop is 'y', arr is ['z']
  8. perform i++, now i is 2
  9. test i < arr.length, false since 2 > 1
  10. completed

Comments

1

This is because at the end of the second loop, the array is ['z'], i is 1, and arr.length is 1 as well. However, before the next iteration, i is incremented to 2 which is greater than arr.length = 1, which effectively stops the loop.

Comments

1

Array.prototype.shift mutates an array by both removing the first element and decreasing its length property.

Therefore, before you get to the 3rd element (z), arr's length is 1. However, i is 2. Your for loop exits because 2 > 1; thus, you don't see z logged to the console.

Comments

1

Your changing the length every time you do an array shift

let arr = ['x', 'y', 'z'];

for (let i = 0; i <= 2; i++) {
  let prop = arr.shift();
  console.log(prop);
  console.log(arr, `${i} <= ${arr.length}`);
}

Comments

1

z is not getting printed because the value of i becomes greater then the length of array when it reaches z, which is 1. the loop wont run further as i<array.length is violated. i will be 2 and length will be 1

You can use a while loop like this

let arr = ['x', 'y', 'z'];
let i=0;
var x=arr.length;
while(i<x) {
    let prop = arr.shift();
    console.log(prop); 
    if(i<=arr.length)
    console.log(arr, `${i} <= ${arr.length}`);
    i++;
}

Comments

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.