Please support this book: buy it or donate

13. The non-values undefined and null



Many programming languages have one “non-value” called null. It indicates that a variable does not currently point to an object. For example, when it hasn’t been initialized, yet.

In contrast, JavaScript has two of them: undefined and null.

13.1. undefined vs. null

Both values are very similar and often used interchangeably. How they differ is therefore subtle. The language itself makes the following distinction:

  • undefined means “not initialized” (e.g. a variable) or “not existing” (e.g. a property of an object).
  • null means “the intentional absence of any object value” (a quote from the language specification).
    Programmers may make the following distinction:

  • undefined is the non-value used by the language (when something is uninitialized etc.).

  • null means “explicitly switched off”. That is, it helps implement a type that comprises both meaningful values and a meta-value that stands for “no meaningful value”. Such a type is called option type or maybe type in functional programming.

13.2. Occurrences of undefined and null

The following subsections describe where undefined and null appear in the language. We’ll encounter several mechanisms that are explained in more detail later in this book.

13.2.1. Occurrences of undefined

Uninitialized variable myVar:

  1. let myVar;
  2. assert.equal(myVar, undefined);

Parameter x is not provided:

  1. function func(x) {
  2. return x;
  3. }
  4. assert.equal(func(), undefined);

Property .unknownProp is missing:

  1. const obj = {};
  2. assert.equal(obj.unknownProp, undefined);

If you don’t explicitly specify the result of a function via the return operator, JavaScript returns undefined for you:

  1. function func() {}
  2. assert.equal(func(), undefined);

13.2.2. Occurrences of null

The prototype of an object is either an object or, at the end of a chain of prototypes, null. Object.prototype does not have a prototype:

  1. > Object.getPrototypeOf(Object.prototype)
  2. null

If you match a regular expression (such as /a/) against a string (such as 'x'), you either get an object with matching data (if matching was successful) or null (if matching failed):

  1. > /a/.exec('x')
  2. null

The JSON data format does not support undefined, only null:

  1. > JSON.stringify({a: undefined, b: null})
  2. '{"b":null}'

13.3. Checking for undefined or null

Checking for either:

  1. if (x === null) ···
  2. if (x === undefined) ···

Does x have a value?

  1. if (x !== undefined && x !== null) {
  2. // ···
  3. }
  4. if (x) { // truthy?
  5. // x is neither: undefined, null, false, 0, NaN, ''
  6. }

Is x either undefined or null?

  1. if (x === undefined || x === null) {
  2. // ···
  3. }
  4. if (!x) { // falsy?
  5. // x is: undefined, null, false, 0, NaN, ''
  6. }

Truthy means “is true if coerced to boolean”. Falsy means “is false if coerced to boolean”. Both concepts are explained properly in the chapter on booleans.

13.4. undefined and null don’t have properties

undefined and null are the two only JavaScript values where you get an exception if you try to read a property. To explore this phenomenon, let’s use the following function, which reads (“gets”) property .foo and returns the result.

  1. function getFoo(x) {
  2. return x.foo;
  3. }

If we apply getFoo() to various value, we can see that it only fails for undefined and null:

  1. > getFoo(undefined)
  2. TypeError: Cannot read property 'foo' of undefined
  3. > getFoo(null)
  4. TypeError: Cannot read property 'foo' of null
  5. > getFoo(true)
  6. undefined
  7. > getFoo({})
  8. undefined

13.5. The history of undefined and null

In Java (which inspired many aspects of JavaScript), initialization values depend on the static type of a variable:

  • Variables with object types are initialized with null.
  • Each primitive type has its own initialization value. For example, int variables are initialized with 0.
    In JavaScript, each variable can hold both object values and primitive values. Therefore, if null means “not an object”, JavaScript also needs an initialization value that means “neither an object nor a primitive value”. That initialization value is undefined.