Why does Javascript `iterator.next()` return an object?
Are there under-the-hood optimizations that skip the allocation of the object return by
next()
?
Yes. Those iterator result objects are small and usually short-lived. Particularly in for … of
loops, the compiler can do a trivial escape analysis to see that the object doesn't face the user code at all (but only the internal loop evaluation code). They can be dealt with very efficiently by the garbage collector, or even be allocated directly on the stack.
Here are some sources:
- JS inherits it functionally-minded iteration protocol from Python, but with results objects instead of the previously favoured
StopIteration
exceptions - Performance concerns in the spec discussion (cont'd) were shrugged off. If you implement a custom iterator and it is too slow, try using a generator function
- (At least for builtin iterators) these optimisations are already implemented:
The key to great performance for iteration is to make sure that the repeated calls to
iterator.next()
in the loop are optimized well, and ideally completely avoid the allocation of theiterResult
using advanced compiler techniques like store-load propagation, escape analysis and scalar replacement of aggregates. To really shine performance-wise, the optimizing compiler should also completely eliminate the allocation of theiterator
itself - theiterable[Symbol.iterator]()
call - and operate on the backing-store of the iterable directly.
Bergi answered already, and I've upvoted, I just want to add this:
Why should you even be concerned about new object being returned? It looks like:
{done: boolean, value: any}
You know, you are going to use the value
anyway, so it's really not an extra memory overhead. What's left? done: boolean
and the object itself take up to 8 bytes each, which is the smallest addressable memory possible and must be processed by the cpu and allocated in memory in a few pico- or nanoseconds (I think it's pico- given the likely-existing v8 optimizations). Now if you still care about wasting that amount of time and memory, than you really should consider switching to something like Rust+WebAssembly from JS.