The primitive
Values are converted to booleans as follows:
There are three ways any value can be converted to a boolean:
Boolean(value)
| (Invoked as a function, not as a constructor) |
value ? true : false
| |
!!value
| A single “not” converts to negated boolean; use twice for the nonnegated conversion. |
I prefer Boolean()
, because it is more descriptive. Here are some examples:
- > Boolean(undefined)
- false
- > Boolean(null)
- false
- > Boolean(0)
- false
- > Boolean(1)
- true
- > Boolean(2)
- true
- > Boolean('')
- false
- > Boolean('abc')
- true
- true
Truthy and Falsy Values
undefined
,null
- Boolean:
false
- Number:
0
,NaN
- String:
''
All other values—including all objects, even empty objects, empty arrays, and new Boolean(false)
—are truthy. Because undefined
and null
are falsy, you can use the if
statement to check whether a variable x
has a value:
if
(
x
)
{
// x has a value
}
The caveat is that the preceding check interprets all falsy values as “does not have a value,” not just undefined
and . But if you can live with that limitation, you get to use a compact and established pattern.
Pitfall: all objects are truthy
All objects are truthy:
- > Boolean(new Boolean(false))
- true
- > Boolean([])
- true
- > Boolean({})
- true
- > Number({ valueOf: function () { return 123 } })
- 123
- > String({ toString: function () { return 'abc' } })
- 'abc'
History: Why are objects always truthy?
The conversion to boolean is different for historic reasons. For ECMAScript 1, it was decided to not enable objects to configure that conversion (e.g., via a toBoolean()
method). The rationale was that the boolean operators ||
and &&
preserve the values of their operands. Therefore, if you chain those operators, the same value may be checked multiple times for truthiness or falsiness. Such checks are cheap for primitives, but would be costly for objects if they were able to configure their conversion to boolean. ECMAScript 1 avoided that cost by making objects always truthy.
In this section, we cover the basics of the And (&&), Or (||), and Not (!) logical operators.
Binary logical operators are:
- Value-preserving
- They always return either one of the operands, unchanged:
- Short-circuiting
- The second operand is not evaluated if the first operand already determines the result. For example (the result of
console.log
isundefined
):
- > true || console.log('Hello')
- true
- > false || console.log('Hello')
- Hello
- undefined
That is uncommon behavior for operators. Normally, all operands are evaluated before an operator is invoked (just like for functions).
Logical And (&&)
If the first operand can be converted to false
, return it. Otherwise, return the second operand:
- > true && false
- false
- > false && 'def'
- false
- > '' && 'def'
- > 'abc' && 'def'
- 'def'
If the first operand can
- > true || false
- true
- > true || 'def'
- true
- > 'abc' || 'def'
- 'abc'
- > '' || 'def'
- 'def'
Pattern: providing a default value
Sometimes
theValue
||
defaultValue
Example 1: a default for a parameter
This is the most common use of ||
as a default operator. Consult Optional Parameters for more on optional parameters.
Example 2: a default for a property
The object options
may or may not have the property title
. If it is missing, the value 'Untitled'
should be used when setting the title:
setTitle
(
options
.
title
||
'Untitled'
);
Example 3: a default for the result of a function
The function countOccurrences
counts how often regex
matches inside str
:
function
(
regex
,
str
)
{
// Omitted: check that /g is set for `regex`
return
(
str
.
match
(
regex
)
||
[]).
length
;
}
The problem is that match()
(see ) either returns an array or null
. Thanks to ||
, a default value is used in the latter case. Therefore, you can safely access the property length
in both cases.
Logical Not (!)
- > !true
- false
- > !43
- false
- > !''
- true
- > !{}
- false
The following operators are covered elsewhere:
- Equality operators:
===
,!==
,==
,!=
(see Equality Operators: === Versus ==) - Ordering operators:
>
,>=
,<
,<=
(see )
The function Boolean
can be invoked in two ways:
Boolean(value)
- As a normal function, it converts
value
to a primitive boolean (see Converting to Boolean):
- > Boolean(0)
- false
- > typeof Boolean(false) // no change
- 'boolean'
- As a constructor, it creates a new instance of
Boolean
(see ), an object that wraps (after converting it to a boolean). For example:
The former invocation is the common one.