Javascript Array methods such as forEach
have a thisArg
parameter, which is used as the context for invoking the callback:
array.fo
On the Es-discuss mailing list you find in answer http://article.gmane.org/gmane.comp.lang.javascript.ecmascript4.general/4770
The other methods with callbacks take a 'thisArg' not because it is needed or even useful, but for compatibility, because they already do in existing implementations that provide these functions.
You can always use this method :
array.reduce(callback.bind(context), initialValue);
... in order to attach a specific context to the callback function.
It becomes messy with two optional arguments, since reduce
(Right
) already covers two functionalities (see Wikipedia), which are distinguished in pure languages (e.g. named foldl
and foldl1
in Haskell). To cite Brendan Eich:
So this would mean reduce takes one callback argument and two optional arguments: thisObject and init. Which one should come first? The more common one is probably init, but then you separate the callback arg from the "thisObject" arg, which is maybe okay. Multiple optional arguments are kinda messy this way...
Alternatively, we could just eliminate that extra "thisObject" argument, since people can always [use binding].
I don't think it's a big issue, since these functional higher-order-functions are mostly used with lamdba-function-expressions anyway (like in your example). Of course there's a little inconsistency, but we can live with that. Image the alternative:
array.reduce(callback[, initialValue[, thisArg]])
Can't be really used, we cannot really determine "if an initialValue was provided" since that means arguments.length < 2
- we could pass undefined
literally as well. So that means
array.reduce(callback[, thisArg[, initialValue]])
which is ugly since we always needed to pass null
or something to thisArg
if we only wanted an initial value.
You noticed that already in your comment to Kangax ("The second optional argument functions differently than normal optional arguments, […] its presence or absence changes the behavior"), but I can't support your statement
this behavior could be easily emulated by simply calling
array.slice(1).reduce(fn,array[0])
as that would a) not work with a complex (chained) expression instead of the array
variable and b) is cumbersome.