Reputation: 4133
Curiously,
['a', 'b', 'c'].lastIndexOf('b', undefined)
returns -1 while the following:
['a', 'b', 'c'].lastIndexOf('b')
returns 1 (at least on Firefox 65's scratchpad).
I assumed passing undefined
would have the same result as passing no argument.
However it seems
['a', 'b', 'c'].lastIndexOf('a', undefined)
does return 0 as expected, which makes me believe my undefined
gets converted to 0.
I understand the default value of the index
parameter in lastIndexOf
points to the last element of the array.
But shouldn't passing undefined
have the same behaviour as passing no argument?
Upvotes: 3
Views: 1095
Reputation: 102174
I previously wrote a comment explaining that, according to the polyfill at MDN, the undefined
as the second argument of Array.prototype.lastIndexOf
(in the polyfill the parameter named n
) indeed gets converted to 0
by these steps:
n = Number(undefined)
=> converts undefined
to NaN
.if(n != n) n = 0
=> checks for NaN
and converts it to 0.let n = Number(undefined);
if (n != n) n = 0;
console.log(n);
Since this is just the polyfill at MDN it seemed to me that it wasn't worth a proper answer. However, the spec at ECMA-International says the same about Array.prototype.lastIndexOf(searchElement[,fromIndex])
:
If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len-1.
Where len-1
is obviously the last index of the array. Then, we have at ToInteger
:
- Let number be ToNumber(argument).
- ReturnIfAbrupt(number).
- If number is NaN, return +0.
In conclusion, your undefined
gets converted to 0
and, therefore, passing undefined
as the second argument of Array.prototype.lastIndexOf
is different from passing nothing.
EDIT
Given your last comment I reckon that the cause of your misunderstanding is clear. You see, there is no default parameter here, and this whole issue has nothing to do with it. Let me explain:
As you know, in JavaScript we can pass more arguments than parameters or less arguments than parameters. If we pass too few arguments, the missing parameters are undefined
. This is easy to show:
function foo(parameter1, parameter2) {
console.log("parameter 2 is " + parameter2)
};
foo("bar");
foo("bar", undefined);
As you can see, passing nothing or passing undefined
has the same effect. However, this is not what's happening here. In the polyfill the function uses the pseudo argument array-like arguments
to get the second argument, testing for arguments.length > 1
. Therefore, when you say...
Does undefined count as a passed argument? I thought it didn't.
It does when you take into account the length of the arguments
array-like object. And, in that case, the difference does matter:
function foo(parameter1, parameter2) {
if (arguments.length > 1) {
console.log("parameter 2 is " + arguments[1])
} else {
console.log("no second parameter")
}
};
foo("bar");
foo("bar", undefined);
Upvotes: 3