Generic iteration method idea with example implementation and tests
# Renki Ivanko (9 years ago)
The methods could be added to the Object
constructor and used like so:
const {map, filter, reduce} = Object
# Renki Ivanko (9 years ago)
To clarify, the few currently implemented methods are just to demonstrate
the idea; the full implementation should have the other methods like
every()
to allow breaking the iteration and forEach()
for side-effects.
Regarding the mention of lazy iteration, the point is that Array.from()
,
which is required to use the Array
iteration methods on other types,
transforms the iterator upfront, while, with a generic every()
method, it
would be possible to process only part of the iterable before breaking.
ES5 added the
Array
iteration methods for iterating over, transforming and reducing arrays, which arguably offer benefits in readability and description of intent, but there are certain pitfalls with applying the methods to the other collection types, which have increased in ES2015 with the addition of new types likeMap
andSet
. I've made a table as illustration with the different methods of looping or iterating over objects and the minimum 'plumbing' required: goo.gl/71dQsGIt's apparent that the
for..of
loop syntax is the most uniform approach to traversing collections, while trying to use theArray
iteration methods requires additional steps and, in the case of iterable objects, requires transforming them to arrays, which loses the benefits of the lazy iteration. Usage of thefor..of
loops also varies depending on whether entries (key-value pairs) or values are used. A solution would be to offer the familiar semantics of the ES5Array
iteration methods that would support the existing collection types, and also allow defining support for new types. I've made an example implementation of this idea: slikts/esnext-generic-iteration/blob/master/src/iteration.js (the other files in the repository implement reconstructing object types, polyfilling native support and a basic test suite).The implementation works by adding two new
Symbol
properties to the iterable objects:@@shape
and@@reconstruct
. Shape can be one of the values of@@shape.indexed
or@@shape.entries
. The generic iteration methods use the shape properties to normalize the return values of the iterators, allowing the same signatures for methods and callbacks to be used for all the various types. The@@reconstruct
property returns a method that returns a reconstructor object that has a method for accepting a value and an optional key, and a property with the resulting collection, whose type is based on the@@species
property of the constructor. This allows for the same behavior as with subclassed native arrays, where the output of the iteration methods will be constructed based on the@@species
property. If the iterable object does not support the reconstructor protocol, the result is anArray
object.Some code examples:
The method and callback signatures in this implementation match those of the
Array
iteration methods.An argument for the desirability of generic iterator methods is the inclusion of similar methods in utility libraries like lodash that deal with collections.
Additional thought: this approach makes it very simple to define an iterable object like has previously been proposed with
Dict
.