This one was short enough to keep in the title but I’ll also add my understanding.
My understanding is any variable (regardless of using ‘var’, ‘let’, or ‘const’), if you referenced without any declaration results in a ‘Reference Error’
This is the behavior of functions as well (arrow and regular).
So why does the following:
console.log(typeof foo)
return ‘undefined’. If I never declared it? Why isn’t it a ‘Reference Error’?
2
Answers
typeof
is an exceptional case. In addition to doing a normal thing on a value that’s passed to it like any other operator, only when its operand is a plain name, it has the extra weird behavior of checking whether that name is in scope and evaluating to"undefined"
without throwing an error if it isn’t.The relevant part of the language specification is ECMAScript 2025 13.5.3:
When you don’t know whether something’s in scope and that something isn’t a property of the global object, it can be necessary1 to rely on this behavior – in a universal module definition (UMD) kind of pattern, for example, where you might check if
typeof module === "undefined"
to decide how to export a library (because your code might be inside a(function (module) { /* your code */ })(…)
kind of wrapper). This is a pretty rare situation.Other times, you might want to check whether some API exists on the global object, and since this
typeof
behavior exists, it can be an easy way to get the job done.This isn’t a situation that requires the use of this
typeof
quirk, since it was always possible to get the global object in a generic way even beforeglobalThis
was introduced for a"SharedWorker" in globalThis
-style test. But since thetypeof
quirk is a thing, may as well use it here too, depending on your preferences.1 Well, you could also use a
try
, but that would be more verbose, and has some subtleties if you want to wrap it in a function. Maybe still arguably better language design in the end, though.typeof
has special behavior when the argument is an identifier, so you can test whether the variable has been declared and initialized.From MDN
Here’s a code snippet to demonstrate: