The for loop uses array access "items[j]", and the while loop uses "items.shift". At the end of the for loop 'items' is still the same, at the end of the while loop 'items' is empty.
Agreed. The context of this problem was a discussion with a colleague about using this in the order of a queue where the items array would represent transformations to apply to another object. Point taken, though!
The original test isn't really valid for comparing loops and your tests prove it. The for loop on my machine does 248MM ops/sec and the while (with no mutation) does 243MM, but the while loop with mutation is 0.44 ops/sec. So performance is basically the same when the workload of the loop is the same.