Sometimes the simplest things bee 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}`);
}
Sometimes the simplest things bee 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 e 'z' doesn't show up with this code as part of the console.log(prop)?
Share Improve this question asked Mar 6, 2019 at 16:12 totalnoobtotalnoob 2,74110 gold badges39 silver badges72 bronze badges 3-
Because you're adjusting the length of the array with every
shift
. – Scott Sauyet Commented Mar 6, 2019 at 16:18 - by z, shouldn't the length be 1 with i being 1, 1 <= 1? – totalnoob Commented Mar 6, 2019 at 16:19
-
But by then
i
is 2. – Scott Sauyet Commented Mar 6, 2019 at 16:25
6 Answers
Reset to default 4You 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}`);
}
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 remended 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:
- set
arr
to ['x', 'y', 'z'] - set
i
to 0 - test
i <= arr.length
, true since 0 <= 3 - do loop body,
prop
is'x'
,arr
is['y', 'z']
- perform
i++
, nowi
is 1 - test
i < arr.length
, true since 1 <= 2 - do loop body,
prop
is'y'
,arr
is['z']
- perform
i++
, nowi
is 2 - test
i < arr.length
, false since 2 > 1 - pleted
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.
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.
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}`);
}
z
is not getting printed because the value of i
bees 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++;
}