There was a Function.prototype.arity
property purposed for getting number of arguments function expects. Now it is obsolete (since JS 1.4), and the same goal has Function.prototype.length
.
But recently I've found an article in the documentation about Array.prototype.reduce
method. And it clearly says that the method has property length
equal to 1
:
The
length
property of thereduce
method is 1.
This exact article has a header with number of arguments, and there are two of them:
Array.prototype.reduce ( callbackfn [ , initialValue ] )
callbackfn
and initialValue
(optional).
So it is not clear to me, what exactly the purpose of length
property.
If it is used to give useful information to developer, then it actually does not.
If it is just a technical automatically-generated property that just indicates number of arguments in function definition, then why don't maintain its consistency?
Array.prototype.reduce
's length
is 1 because the second parameter is optional.*
So it is not clear to me, what exactly the purpose of
length
property.
To tell the developer how many declared parameters it has prior to the first parameter with a default value (if any) or the rest parameter (if any), whichever is earliest in the parameter list. Or as the spec puts it:
The value of the
length
property is an integer that indicates the typical number of arguments expected by the function.
The exact algorithm is in the spec's Static Semantics: ExpectedArgumentCount section.
If it is used to give useful information to developer, then it actually does not.
Well, that's a matter of opinion. :-)
When you have a language like JavaScript where functions can only express an expectation but may be called with fewer or more arguments, and particularly when you add the concepts of default parameter values and rest parameters, it's not surprising that the arity of function is a bit of a soft concept.
Some fun examples:
function ex1(a) { } // length is 1, of course
function ex2(a, b = 42) { } // length is 1, `b` has a default
function ex3(a, b = 42, c) { } // length is 1, `b` has a default and
// `c` is after `b`
function ex4(a, ...rest) { } // length is 1 yet again, rest parameter doesn't count
* In ES5, its declaration in JavaScript would be:
function reduce(callback) {
// ...
}
...and then it would use arguments.length
to determine whether you'd supposed an initialValue
.
In ES2015+ (aka "ES6"+), it would either still be like that, or be like this:
function reduce(callback, ...args) {
// ...
}
...and use args.length
to see if there was an initial value.
Or possibly like this:
const omitted = {};
function reduce(callback, initialValue = omitted) {
// ...
}
...and then use initialValue === omitted
to know whether you'd supplied an initial value. (The default value of initialValue
can't be undefined
or null
or similar because the function has to branch based on whether the argument was provided [not what its value is]. But we can do that with object identity.)