Lead Product Evangelist @Kentico, Founding partner @craftbrewingbiz. love to learn / teach web dev & software engineering, collecting vinyl records, mowing my lawn, craft 🍺
Another thing I point out to devs new to javascript is the callback passed to forEach is necessarily an impure function since it doesn't return anything.
If a dev sees it in code they should assume it is mutating state.
Whereas, although map can be abused to mutate state, since it always returns a new array, its design implies its callback is a pure function.
map and filter are best treated as using pure functions.
Because forEach doesn't work how the above two array methods work, I tend to avoid using it altogether and instead use the modern for ... of iteration approach when I need to mutate state.
Thanks for writing this comparison. I've seen many devs get confused about this stuff 👍
Implies is a strong word... I'd say, "allows for". Per the ECMA standard, map() guarantees invocation order against the elements of the array, something that would be unnecessary to specify in a function that implies a pure function callback.
The standard itself explicitly says that while map doesn't mutate the object on which it is called, the callback function may mutate it (not just any old side effect here like console.log(), but a mutation of the object being called)... and there's an odd rule that if you delete an element from the array during the invocation of map(), but before map visits that element, that element will not be visited.
Sure, it's better style if it is pure, but the implication, if anything, is that it may be impure.
Lead Product Evangelist @Kentico, Founding partner @craftbrewingbiz. love to learn / teach web dev & software engineering, collecting vinyl records, mowing my lawn, craft 🍺
Another thing I point out to devs new to javascript is the callback passed to
forEach
is necessarily an impure function since it doesn't return anything.If a dev sees it in code they should assume it is mutating state.
Whereas, although
map
can be abused to mutate state, since it always returns a new array, its design implies its callback is a pure function.map
andfilter
are best treated as using pure functions.Because
forEach
doesn't work how the above two array methods work, I tend to avoid using it altogether and instead use the modernfor ... of
iteration approach when I need to mutate state.Thanks for writing this comparison. I've seen many devs get confused about this stuff 👍
Implies is a strong word... I'd say, "allows for". Per the ECMA standard, map() guarantees invocation order against the elements of the array, something that would be unnecessary to specify in a function that implies a pure function callback.
The standard itself explicitly says that while map doesn't mutate the object on which it is called, the callback function may mutate it (not just any old side effect here like console.log(), but a mutation of the object being called)... and there's an odd rule that if you delete an element from the array during the invocation of map(), but before map visits that element, that element will not be visited.
Sure, it's better style if it is pure, but the implication, if anything, is that it may be impure.
Those are good points.
In much of the code I see,
map
andfilter
are used with pure functions.So, despite what the language allows, the use of them implies pure functions in my experience.
Following this pattern means you don't have to worry about the scenario you describe.