+
)==
vs. ===
void
operatorJavaScript’s operators may seem quirky. With the following two rules, they are easier to understand:
If an operator gets operands that don’t have the proper types, it rarely throws an exception. Instead, it coerces (automatically converts) the operands so that it can work with them. Let’s look at two examples.
First, the multiplication operator can only work with numbers. Therefore, it converts strings to numbers before computing its result.
> '7' * '3'21
Second, the square brackets operator ([ ]
) for accessing the properties of an object can only handle strings and symbols. All other values are coerced to string:
const obj = {};
'true'] = 123;
obj[
// Coerce true to the string 'true'
.equal(obj[true], 123); assert
As mentioned before, most operators only work with primitive values. If an operand is an object, it is usually coerced to a primitive value – for example:
> [1,2,3] + [4,5,6]'1,2,34,5,6'
Why? The plus operator first coerces its operands to primitive values:
> String([1,2,3])'1,2,3'
> String([4,5,6])'4,5,6'
Next, it concatenates the two strings:
> '1,2,3' + '4,5,6''1,2,34,5,6'
+
)The plus operator works as follows in JavaScript:
String mode lets us use +
to assemble strings:
> 'There are ' + 3 + ' items''There are 3 items'
Number mode means that if neither operand is a string (or an object that becomes a string) then everything is coerced to numbers:
> 4 + true5
Number(true)
is 1
.
The plain assignment operator is used to change storage locations:
= value; // assign to a previously declared variable
x .propKey = value; // assign to a property
obj= value; // assign to an Array element arr[index]
Initializers in variable declarations can also be viewed as a form of assignment:
const x = value;
let y = value;
JavaScript supports the following assignment operators:
+= -= *= /= %=
[ES1]
+=
can also be used for string concatenation**=
[ES2016]&= ^= |=
[ES1]<<= >>= >>>=
[ES1]||= &&= ??=
[ES2021]Logical assignment operators work differently from other compound assignment operators:
Assignment operator | Equivalent to | Only assigns if a is |
---|---|---|
a ||= b |
a || (a = b) |
Falsy |
a &&= b |
a && (a = b) |
Truthy |
a ??= b |
a ?? (a = b) |
Nullish |
Why is a ||= b
equivalent to the following expression?
a || (a = b)
Why not to this expression?
a = a || b
The former expression has the benefit of short-circuiting: The assignment is only evaluated if a
evaluates to false
. Therefore, the assignment is only performed if it’s necessary. In contrast, the latter expression always performs an assignment.
For more on ??=
, see §14.4.5 “The nullish coalescing assignment operator (??=
) [ES2021]”.
For operators op
other than || && ??
, the following two ways of assigning are equivalent:
myvar op= value
myvar = myvar op value
If, for example, op
is +
, then we get the operator +=
that works as follows.
let str = '';
+= '<b>';
str += 'Hello!';
str += '</b>';
str
.equal(str, '<b>Hello!</b>'); assert
==
vs. ===
JavaScript has two kinds of equality operators: loose equality (==
) and strict equality (===
). The recommendation is to always use the latter.
Other names for
==
and ===
==
is also called double equals. Its official name in the language specification is abstract equality comparison.===
is also called triple equals.==
and !=
)Loose equality is one of JavaScript’s quirks. It often coerces operands. Some of those coercions make sense:
> '123' == 123true
> false == 0true
Others less so:
> '' == 0true
Objects are coerced to primitives if (and only if!) the other operand is primitive:
> [1, 2, 3] == '1,2,3'true
> ['1', '2', '3'] == '1,2,3'true
If both operands are objects, they are only equal if they are the same object:
> [1, 2, 3] == ['1', '2', '3']false
> [1, 2, 3] == [1, 2, 3]false
> const arr = [1, 2, 3];
> arr == arrtrue
Lastly, ==
considers undefined
and null
to be equal:
> undefined == nulltrue
===
and !==
)Strict equality never coerces. Two values are only equal if they have the same type. Let’s revisit our previous interaction with the ==
operator and see what the ===
operator does:
> false === 0false
> '123' === 123false
An object is only equal to another value if that value is the same object:
> [1, 2, 3] === '1,2,3'false
> ['1', '2', '3'] === '1,2,3'false
> [1, 2, 3] === ['1', '2', '3']false
> [1, 2, 3] === [1, 2, 3]false
> const arr = [1, 2, 3];
> arr === arrtrue
The ===
operator does not consider undefined
and null
to be equal:
> undefined === nullfalse
I recommend to always use ===
. It makes your code easier to understand and spares you from having to think about the quirks of ==
.
Let’s look at two use cases for ==
and what I recommend to do instead.
==
: comparing with a number or a string==
lets you check if a value x
is a number or that number as a string – with a single comparison:
if (x == 123) {
// x is either 123 or '123'
}
I prefer either of the following two alternatives:
if (x === 123 || x === '123') ···
if (Number(x) === 123) ···
You can also convert x
to a number when you first encounter it.
==
: comparing with undefined
or null
Another use case for ==
is to check if a value x
is either undefined
or null
:
if (x == null) {
// x is either null or undefined
}
The problem with this code is that you can’t be sure if someone meant to write it that way or if they made a typo and meant === null
.
I prefer either of the following two alternatives:
if (x === undefined || x === null) ···
if (!x) ···
A downside of the second alternative is that it accepts values other than undefined
and null
, but it is a well-established pattern in JavaScript (to be explained in detail in §15.3 “Truthiness-based existence checks”).
The following three conditions are also roughly equivalent:
if (x != null) ···
if (x !== undefined && x !== null) ···
if (x) ···
===
: Object.is()
Method Object.is()
compares two values:
> Object.is(123, 123)true
> Object.is(123, '123')false
It is even stricter than ===
. For example, it considers NaN
, the error value for computations involving numbers, to be equal to itself:
> Object.is(NaN, NaN)true
> NaN === NaNfalse
That is occasionally useful. For example, you can use it to implement an improved version of the Array method .indexOf()
:
const myIndexOf = (arr, elem) => {
return arr.findIndex(x => Object.is(x, elem));
; }
myIndexOf()
finds NaN
in an Array, while .indexOf()
doesn’t:
> myIndexOf([0,NaN,2], NaN)1
> [0,NaN,2].indexOf(NaN)-1
The result -1
means that .indexOf()
couldn’t find its argument in the Array.
Operator | name |
---|---|
< |
less than |
<= |
Less than or equal |
> |
Greater than |
>= |
Greater than or equal |
JavaScript’s ordering operators (tbl. 3) work for both numbers and strings:
> 5 >= 2true
> 'bar' < 'foo'true
<=
and >=
are based on strict equality.
The ordering operators don’t work well for human languages
The ordering operators don’t work well for comparing text in a human language, e.g., when capitalization or accents are involved. The details are explained in §20.6 “Comparing strings”.
The following operators are covered elsewhere in this book:
??
) for default valuesThe next two subsections discuss two operators that are rarely used.
The comma operator has two operands, evaluates both of them and returns the second one:
> 'a', 'b''b'
For more information on this operator, see Speaking JavaScript.
void
operatorThe void
operator evaluates its operand and returns undefined
:
> void (3 + 2)undefined
For more information on this operator, see Speaking JavaScript.
Quiz
See quiz app.