61

I'm wallowing in ES2015+ luxury with a few projects right now and am wondering whether I can get rid of the much hated crutch to check for undefined in the new wonderland.

Is there a shorter but still exact way to typeof varName === 'undefined' in ES2015+ already?

Of course I could use default parameters but this also feels like an unnecessary assignment.

function coolFn(a = null){
   if (a===null) console.log("no a supplied");
}
Michał Perłakowski
  • 70,955
  • 24
  • 137
  • 155
Hedge
  • 13,498
  • 35
  • 122
  • 223
  • 3
    What do you mean by "better"? – Pointy Jan 04 '16 at 17:25
  • 4
    Why use a typeof check in the first place? `if(a===undefined)` – epascarello Jan 04 '16 at 17:25
  • @Pointy I meant shorter to write but still covering all cases. – Hedge Jan 04 '16 at 17:28
  • 3
    why wouldn't you just check if( !a ) ? I don't see why the value being null or undefined actually matters - whereas `a` actually having a value seems to be the true check. that is - of course, unless you are going to allow for `false` or `0` to be valid values =P – Jonathon Hibbard Jan 04 '16 at 17:28
  • 5
    Or `(a == null)` which covers both `null` and `undefined`. – Pointy Jan 04 '16 at 17:30
  • @JonathonHibbard that's precisely why you'd want to make an explicit check for `=== undefined` !! – Alnitak Jan 04 '16 at 17:31
  • @Alnitak yeah - i gather that. just thinking something as simple as a `!` might be all the guy really needs - but don't know for sure. – Jonathon Hibbard Jan 04 '16 at 17:40
  • 2
    @JonathonHibbard Your question being "why wouldn't you?". Because the OP clearly wants to be able to distinguish the difference between the parameter being passed and an otherwise legal (but falsey) value. – Alnitak Jan 04 '16 at 17:42
  • i think you're assuming a lot by that @Alnitak - he never indicated that a `0` or `false`would be valid values... he also never indicated they would be either. which is why i asked =P – Jonathon Hibbard Jan 04 '16 at 17:43
  • He absolutely did indicate that the test is for a _missing value_ - it's there in the console log message `"No a supplied"` – Alnitak Jan 04 '16 at 17:44
  • plus there's the comment to my answer (pre-dating your first comment) saying that what I'd asked for was what he was looking for. Oh, and the question title. – Alnitak Jan 04 '16 at 17:47
  • That doesn't "absolutely" mean that - not at all. only the OP would know what is considered a "valid" value. but assuming that `false` (or even `0`) is considered a valid value is a huge assumption – Jonathon Hibbard Jan 04 '16 at 17:48
  • 1
    Assuming that `0` (or `false`) isn't a valid value is a worse assumption. – Alnitak Jan 04 '16 at 17:51
  • I agree @Alnitak - that's why i asked - rather than just `assuming` =) – Jonathon Hibbard Jan 04 '16 at 17:53
  • 1
    Sorry for being unclear in the first place. I want to be able to distinguish undefined from false or an empty array. – Hedge Jan 04 '16 at 18:37

2 Answers2

85

Just check for varName === undefined.

In older browsers it was possible to assign an alternate value to the global undefined variable causing that test to fail, but in ES2015+ that's now impossible.

Note that there's no way to distinguish explicitly passing undefined as a parameter from leaving the parameter out altogether other than by looking at arguments.length.

Alnitak
  • 313,276
  • 69
  • 379
  • 466
  • How could I miss that! Yeah, that's already good enough :) I don't need to distinguish between both cases you mentioned. – Hedge Jan 04 '16 at 17:26
  • 5
    Since ES5 you can't alter the global `undefined` property. But you can still shadow it with a local variable. – Oriol Jan 04 '16 at 17:32
  • @Oriol that's true, but if you do that you've only got yourself to blame. What you can't do now is "inject" a different value of `undefined` into the global scope. – Alnitak Jan 04 '16 at 17:33
  • Isn't the inability to redefine `undefined` a matter of `"use strict;"` rather than ES2015? –  Jan 04 '16 at 17:34
  • @torazaburo not to my knowledge – Alnitak Jan 04 '16 at 17:35
  • 3
    @torazaburo [Annex E](http://www.ecma-international.org/ecma-262/5.1/#sec-E) of ES5 lists "The value properties NaN, Infinity, and undefined of the Global Object have been changed to be read-only properties" as an incompatibility with ES3. So the change affects non-strict mode too. – Oriol Jan 04 '16 at 17:39
  • The following could still cause trouble: `function foo(undefined) { return function bar(a) { console.log(a === undefined); }; } console.log(foo(42)());`. –  Jan 04 '16 at 18:16
  • 1
    @torazaburo yes, that's what Oriol was referring to by "shadowing". That's mere "programmer error", though, whereas allowing the overwriting of the global `undefined` property could potentially lead to security problems. – Alnitak Jan 04 '16 at 18:23
  • Please keep in mind that `varName === undefined` will throw a `ReferenceError` if the variable is not defined. – laszlo-horvath Aug 13 '20 at 10:53
25

The only case where typeof varName === 'undefined' is useful is when you don't know whether the variable varName has been declared.

And IMO if you don't know whether your variables are declared, your code has serious problems.

In other cases you have better options:

  • varName === void 0

    This will detect whether varName is undefined.

    void is an operator which receives an argument (you can use whatever instead of 0), and returns undefined.

  • varName === undefined

    This should detect whether varName is undefined.

    However, be aware the global undefined could have been overwritten (before ES5) or shadowed with another value. Therefore I prefer void, which is also shorter.

  • varName == null

    This will detect whether varName is undefined or is null.

  • !varName

    This will detect whether varName is falsy (undefined, null, 0, empty string, NaN, false).

Oriol
  • 225,583
  • 46
  • 371
  • 457