HomepageExploring JavaScript (ES2024 Edition)
You can support this book: buy it or donate
(Ad, please don’t block.)

17 Booleans

The primitive type boolean comprises two values – false and true:

> typeof false
'boolean'
> typeof true
'boolean'

17.1 Converting to boolean

Icon “details”The meaning of “converting to [type]”

“Converting to [type]” is short for “Converting arbitrary values to values of type [type]”.

These are three ways in which you can convert an arbitrary value x to a boolean.

Table 17.1 describes how various values are converted to boolean.

xBoolean(x)
undefinedfalse
nullfalse
booleanx (no change)
number0false, NaNfalse
Other numbers → true
bigint0false
Other numbers → true
string''false
Other strings → true
symboltrue
objectAlways true

Table 17.1: Converting values to booleans.

17.2 Falsy and truthy values

When checking the condition of an if statement, a while loop, or a do-while loop, JavaScript works differently than you may expect. Take, for example, the following condition:

if (value) {}

In many programming languages, this condition is equivalent to:

if (value === true) {}

However, in JavaScript, it is equivalent to:

if (Boolean(value) === true) {}

That is, JavaScript checks if value is true when converted to boolean. This kind of check is so common that the following names were introduced:

Each value is either truthy or falsy. Consulting table 17.1, we can make an exhaustive list of falsy values:

All other values (including all objects) are truthy:

> Boolean('abc')
true
> Boolean([])
true
> Boolean({})
true

17.2.1 Checking for truthiness or falsiness

if (x) {
  // x is truthy
}

if (!x) {
  // x is falsy
}

if (x) {
  // x is truthy
} else {
  // x is falsy
}

const result = x ? 'truthy' : 'falsy';

The conditional operator that is used in the last line, is explained later in this chapter.

Icon “exercise”Exercise: Truthiness

exercises/booleans/truthiness_exrc.mjs

17.3 Truthiness-based existence checks

In JavaScript, if you read something that doesn’t exist (e.g., a missing parameter or a missing property), you usually get undefined as a result. In these cases, an existence check amounts to comparing a value with undefined. For example, the following code checks if object obj has the property .prop:

if (obj.prop !== undefined) {
  // obj has property .prop
}

Due to undefined being falsy, we can shorten this check to:

if (obj.prop) {
  // obj has property .prop
}

17.3.1 Pitfall: truthiness-based existence checks are imprecise

Truthiness-based existence checks have one pitfall: they are not very precise. Consider this previous example:

if (obj.prop) {
  // obj has property .prop
}

The body of the if statement is skipped if:

However, it is also skipped if:

In practice, this rarely causes problems, but you have to be aware of this pitfall.

17.3.2 Use case: was a parameter provided?

A truthiness check is often used to determine if the caller of a function provided a parameter:

function func(x) {
  if (!x) {
    throw new Error('Missing parameter x');
  }
  // ···
}

On the plus side, this pattern is established and short. It correctly throws errors for undefined and null.

On the minus side, there is the previously mentioned pitfall: the code also throws errors for all other falsy values.

An alternative is to check for undefined:

if (x === undefined) {
  throw new Error('Missing parameter x');
}

17.3.3 Use case: does a property exist?

Truthiness checks are also often used to determine if a property exists:

function readFile(fileDesc) {
  if (!fileDesc.path) {
    throw new Error('Missing property: .path');
  }
  // ···
}
readFile({ path: 'foo.txt' }); // no error

This pattern is also established and has the usual caveat: it not only throws if the property is missing, but also if it exists and has any of the falsy values.

If you truly want to check if the property exists, you have to use the in operator:

if (! ('path' in fileDesc)) {
  throw new Error('Missing property: .path');
}

17.4 Conditional operator (? :)

The conditional operator is the expression version of the if statement. Its syntax is:

«condition» ? «thenExpression» : «elseExpression»

It is evaluated as follows:

The conditional operator is also called ternary operator because it has three operands.

Examples:

> true ? 'yes' : 'no'
'yes'
> false ? 'yes' : 'no'
'no'
> '' ? 'yes' : 'no'
'no'

The following code demonstrates that whichever of the two branches “then” and “else” is chosen via the condition, only that branch is evaluated. The other branch isn’t.

const x = (true ? console.log('then') : console.log('else'));

Output:

then

17.5 Binary logical operators: And (x && y), Or (x || y)

The binary logical operators && and || are value-preserving and short-circuiting.

17.5.1 Value-preservation

Value-preservation means that operands are interpreted as booleans but returned unchanged:

> 12 || 'hello'
12
> 0 || 'hello'
'hello'

17.5.2 Short-circuiting

Short-circuiting means if the first operand already determines the result, then the second operand is not evaluated. The only other operator that delays evaluating its operands is the conditional operator. Usually, all operands are evaluated before performing an operation.

For example, logical And (&&) does not evaluate its second operand if the first one is falsy:

const x = false && console.log('hello');
// No output

If the first operand is truthy, console.log() is executed:

const x = true && console.log('hello');

Output:

hello

17.5.3 Logical And (x && y)

The expression a && b (“a And b”) is evaluated as follows:

  1. Evaluate a.
  2. Is the result falsy? Return it.
  3. Otherwise, evaluate b and return the result.

In other words, the following two expressions are roughly equivalent:

a && b
!a ? a : b

Examples:

> false && true
false
> false && 'abc'
false

> true && false
false
> true && 'abc'
'abc'

> '' && 'abc'
''

17.5.4 Logical Or (||)

The expression a || b (“a Or b”) is evaluated as follows:

  1. Evaluate a.
  2. Is the result truthy? Return it.
  3. Otherwise, evaluate b and return the result.

In other words, the following two expressions are roughly equivalent:

a || b
a ? a : b

Examples:

> true || false
true
> true || 'abc'
true

> false || true
true
> false || 'abc'
'abc'

> 'abc' || 'def'
'abc'
17.5.4.1 Legacy use case for logical Or (||): providing default values

ECMAScript 2020 introduced the nullish coalescing operator (??) for default values. Before that, logical Or was used for this purpose:

const valueToUse = receivedValue || defaultValue;

See “The nullish coalescing operator (??) for default values” (§16.4) for more information on ?? and the downsides of || in this case.

Icon “exercise”Legacy exercise: Default values via the Or operator (||)

exercises/booleans/default_via_or_exrc.mjs

17.6 Logical Not (!)

The expression !x (“Not x”) is evaluated as follows:

  1. Evaluate x.
  2. Is it truthy? Return false.
  3. Otherwise, return true.

Examples:

> !false
true
> !true
false

> !0
true
> !123
false

> !''
true
> !'abc'
false