undefined being treated as a missing optional argument

David Herman dherman at mozilla.com
Fri Apr 13 11:48:52 PDT 2012

On Apr 13, 2012, at 11:35 AM, Oliver Hunt wrote:

> What happens if i have:
> function foo(a=1, b=2) { log(a, b, arguments.length); }
> foo();

1, 2, 2

> foo(undefined);

1, 2, 1

> foo(3);

3, 2, 1

> foo(undefined, undefined);

1, 2, 2

> foo(undefined, 3);

1, 3, 2

> foo(3, undefined);

3, 2, 2

> Default values are for when arguments are not passed,

Stated without evidence!

> it does not make logical sense to say that they're the value given just because someone has passed undefined.

It makes perfect sense. But hey, I had the same reaction as you at first, so I sympathize. Default values conceptually represent "no value provided," and the natural way to think of this from a language designer or implementer's perspective is to think about whether the syntax of the call included an argument at the particular position. But this is not the *programmer's* perspective. From the programmer's perspective, it's "do I have a value to provide for this argument?" And in reality, the answer to that question is often a *dynamic* one, not a static one. You often have to make the decision at runtime whether to provide a value for a given argument. When you do, the semantics based on arguments.length has terrible consequences: you either have to write a combinatorial explosion of separate calls (code bloat -- unacceptable), or you just end up reimplementing the default logic by conditionally producing the default value (abstraction violation -- unacceptable).

So after thinking more about it, I came to the conclusion that:

- default values are for when no value *of the expected input type* was provided
- undefined is almost universally used in JS as a sentinel value for "I have no value of the expected input type," because it's not statically typed so it's not possible to express option types
- whenever you need to make conditional decisions about whether you have a value for various arguments, the arguments.length semantics has unacceptable engineering consequences
- in the rare cases where you want to treat undefined as an acceptable value of the expected input type, just don't use default values

> It also makes the behavioural definition more complex.

The behavioral definition is trivial. If the value of an argument with a given default is undefined, you use the default.


More information about the es-discuss mailing list