0% found this document useful (0 votes)
4 views44 pages

JavaScript Draft - Operators, Equality Comparison

The document provides a comprehensive guide to JavaScript expressions and operators, covering various types such as arithmetic, logical, and assignment operators. It explains concepts like operator precedence, equality comparisons, and the use of unary and binary operators, along with examples. Additionally, it includes specific details about unique operators like the nullish coalescing operator and optional chaining.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views44 pages

JavaScript Draft - Operators, Equality Comparison

The document provides a comprehensive guide to JavaScript expressions and operators, covering various types such as arithmetic, logical, and assignment operators. It explains concepts like operator precedence, equality comparisons, and the use of unary and binary operators, along with examples. Additionally, it includes specific details about unique operators like the nullish coalescing operator and optional chaining.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

[Link]

org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#a
ssignment_operators

Operators​ 3

Basic operators, maths​ 3


Terms: “unary”, “binary”, “operand”​ 3
Arithmetic Operators - Maths​ 4
Remainder % (modulo)​ 4
Exponentiation ** (Exponent)​ 4
Plus sign (+) with Strings and Numbers - String concatenation with binary +​ 5
Numeric conversion, unary +​ 5
Operator precedence - Operator precedence​ 6
Assignment operators - Assignment operator =​ 7
Assignment operator = returns a value​ 8
Chaining assignments​ 9
Modify-in-place​ 9
Increment/decrement operators​ 9
Increment/decrement among other operators​ 11
Bitwise(bit a bit) operators (used rarely) - Bitwise operators (MDN)​ 11
Comma ,​ 11
Comma has a very low precedence​ 12
Tasks​ 12
The postfix and prefix forms​ 12
Assignment result​ 13
Type conversions​ 13
Fix the addition​ 14

Equality comparisons and sameness - Comparisons​ 14


Boolean is the result​ 15
Strict equality using === - Strict equality (===)​ 16
A strict equality operator === checks the equality without type conversion.​ 16
Loose equality using ==​ 16
Comparison of different types​ 18
Weird consequences​ 18
Strict-non-equality (!==)​ 19
Same-value equality ([Link])​ 20
Same-value-zero equality​ 20
Abstract equality, strict equality, and same value in the specification​ 20
A model for understanding equality comparisons?​ 20
When to use [Link] versus triple equals​ 22
Caveat: [Link] and NaN​ 23
Comparison with null and undefined​ 23
For a strict equality check ===​ 24
For a non-strict check ==​ 24
For maths and other comparisons < > <= >=​ 24
Strange result: null vs 0​ 24
An incomparable undefined​ 24
Avoid problems​ 24
Summary​ 25
Tasks​ 25
Comparisons​ 25

Logical operators​ 25
|| (OR)​ 26
OR “||” finds the first truthy value​ 26
Bitwise OR (|) Operator​ 27
Syntax​ 27
Description​ 27
Using bitwise OR​ 28
&& (AND)​ 28
AND “&&” finds the first falsy value​ 29
Precedence of AND && is higher than OR ||​ 29
Don’t replace if with || or &&​ 29
! (NOT)​ 30
Truthy / Falsy​ 30
Tasks​ 31
What's the result of OR?​ 31
What's the result of OR'ed alerts?​ 31
What is the result of AND?​ 31
What is the result of AND'ed alerts?​ 32
The result of OR AND OR​ 32
Check the range between​ 32
Check the range outside​ 32
A question about "if"​ 32
Check the login​ 33

Nullish coalescing operator '??'​ 34


Comparison with ||​ 34
Precedence​ 35
Using ?? with && or ||​ 35
Logical nullish assignment (??=)​ 36
Short-circuit evaluation​ 36
Using logical nullish assignment​ 37
Summary​ 37
Operator precedence Table​ 37

Expressions and operators


This chapter documents all the JavaScript language operators, expressions and keywords.
Expressions and operators by category
For an alphabetical listing see the sidebar on the left.
Primary expressions
Basic keywords and general expressions in JavaScript.
this
The this keyword refers to a special property of an execution context.
function
The function keyword defines a function expression.
class
The class keyword defines a class expression.
function*
The function* keyword defines a generator function expression.
yield
Pause and resume a generator function.
yield*
Delegate to another generator function or iterable object.
async function
The async function defines an async function expression.
await
Pause and resume an async function and wait for the promise's resolution/rejection.
[]
Array initializer/literal syntax.
{}
Object initializer/literal syntax.
/ab+c/i
Regular expression literal syntax.
( )
Grouping operator.
Left-hand-side expressions
Left values are the destination of an assignment.
Property accessors
Member operators provide access to a property or method of an object
([Link] and object["property"]).
new
The new operator creates an instance of a constructor.
[Link]
In constructors, [Link] refers to the constructor that was invoked by new.
[Link]
An object exposing context-specific metadata to a JavaScript module.
super
The super keyword calls the parent constructor.
...obj
Spread syntax allows an expression to be expanded in places where multiple arguments
(for function calls) or multiple elements (for array literals) are expected.
Increment and decrement
Postfix/prefix increment and postfix/prefix decrement operators.
A++
Postfix increment operator.
A--
Postfix decrement operator.
++A
Prefix increment operator.
--A
Prefix decrement operator.
Unary operators
A unary operation is an operation with only one operand.
delete
The delete operator deletes a property from an object.
void
The void operator discards an expression's return value.
typeof
The typeof operator determines the type of a given object.
+
The unary plus operator converts its operand to Number type.
-
The unary negation operator converts its operand to Number type and then negates it.
~
Bitwise NOT operator.
!
Logical NOT operator.
Arithmetic operators
Arithmetic operators take numerical values (either literals or variables) as their operands and
return a single numerical value.
+
Addition operator.
-
Subtraction operator.
/
Division operator.
*
Multiplication operator.
%
Remainder operator.
**
Exponentiation operator.
Relational operators
A comparison operator compares its operands and returns a Boolean value based on whether
the comparison is true.
in
The in operator determines whether an object has a given property.
instanceof
The instanceof operator determines whether an object is an instance of another object.
<
Less than operator.
>
Greater than operator.
<=
Less than or equal operator.
>=
Greater than or equal operator.
Note: => is not an operator, but the notation for Arrow functions.
Equality operators
The result of evaluating an equality operator is always of type Boolean based on whether the
comparison is true.
==
Equality operator.
!=
Inequality operator.
===
Identity operator.
!==
Nonidentity operator.
Bitwise shift operators
Operations to shift all bits of the operand.
<<
Bitwise left shift operator.
>>
Bitwise right shift operator.
>>>
Bitwise unsigned right shift operator.
Binary bitwise operators
Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and return standard
JavaScript numerical values.
&
Bitwise AND.
|
Bitwise OR.
^
Bitwise XOR.
Binary logical operators
Logical operators are typically used with boolean (logical) values, and when they are, they
return a boolean value.
&&
Logical AND.
||
Logical OR.
??
Nullish Coalescing Operator.
Conditional (ternary) operator
(condition ? ifTrue : ifFalse)
The conditional operator returns one of two values based on the logical value of the
condition.
Optional Chaining operator
?.
The optional chaining operator returns undefined instead of causing an error if a
reference is nullish (null or undefined).
Assignment operators
An assignment operator assigns a value to its left operand based on the value of its right
operand.
=
Assignment operator.
*=
Multiplication assignment.
**=
Exponentiation assignment.
/=
Division assignment.
%=
Remainder assignment.
+=
Addition assignment.
-=
Subtraction assignment
<<=
Left shift assignment.
>>=
Right shift assignment.
>>>=
Unsigned right shift assignment.
&=
Bitwise AND assignment.
^=
Bitwise XOR assignment.
|=
Bitwise OR assignment.
&&=
Logical AND assignment.
||=
Logical OR assignment.
??=
Logical nullish assignment.
[a, b] = [1, 2]
{a, b} = {a:1, b:2}
Destructuring assignment allows you to assign the properties of an array or object to
variables using syntax that looks similar to array or object literals.
Comma operator
,
The comma operator allows multiple expressions to be evaluated in a single statement
and returns the result of the last expression.
Operators
Arithmetic Operators +, -, *, /
Logical (Boolean) Operators >,<,>=,<=
Relational Operators
Conditional Operator
Nullish coalescing Operator
Elvis Operator

Basic operators, maths


Operators are things like addition +, multiplication *, subtraction -, and so on.
We’ll start with simple operators, then concentrate on JavaScript-specific aspects, not covered
by school arithmetic.

Terms: “unary”, “binary”, “operand”


let’s grasp some common terminology.
●​ An operand – is what operators are applied to. For instance, in the multiplication of 5 *
2 there are two operands: the left operand is 5 and the right operand is 2. Sometimes,
people call these “arguments” instead of “operands”.

●​ An operator is unary if it has a single operand. For example, the unary negation -
reverses the sign of a number:
let x = 1;
x = -x;
alert( x ); // -1, unary negation was applied

●​ An operator is binary if it has two operands. The same minus exists in binary form as
well:
let x = 1, y = 3;
alert( y - x ); // 2, binary minus subtracts values

Formally, in the examples above we have two different operators that share the same symbol:
the negation operator, a unary operator that reverses the sign, and the subtraction operator, a
binary operator that subtracts one number from another.

Arithmetic Operators - Maths

The following math operations are supported:


●​ Addition +,
●​ Subtraction -,
●​ Multiplication *,
●​ Division /,

●​ Remainder %,
●​ Exponentiation **.
The first four are straightforward, while % and ** need a few words about them.

Remainder % (modulo)
The remainder operator %, despite its appearance, is not related to percents.
The result of a % b is the remainder of the integer division of a by b.
For instance:
alert( 5 % 2 ); // 1, a remainder of 5 divided by 2
alert( 8 % 3 ); // 2, a remainder of 8 divided by 3

Returns the remainder left over after you've divided the left number into a number of
integer portions equal to the right number.
8 % 3 (returns 2, as three goes into 8 twice, leaving 2 left over).

Exponentiation ** (Exponent)
The exponentiation operator a ** b multiplies a by itself b times.
For instance:
alert( 2 ** 2 ); // 4 (2 multiplied by itself 2 times)
alert( 2 ** 3 ); // 8 (2 * 2 * 2, 3 times)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2, 4 times)
Mathematically, the exponentiation is defined for non-integer numbers as well. For example, a
square root is an exponentiation by 1/2:
alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root)
alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root)

Raises a base number to the exponent power, that is, the base number multiplied by itself,
exponent times. It was first Introduced in EcmaScript 2016.
5 ** 2 (returns 25, which is the same as 5 * 5).

Plus sign (+) with Strings and Numbers - String


concatenation with binary +
Let’s meet features of JavaScript operators that are beyond school arithmetics.
Usually, the plus operator + sums numbers.
But, if the binary + is applied to strings, it merges (concatenates) them:
let s = "my" + "string";
alert(s); // mystring
Note that if any of the operands is a string, then the other one is converted to a string too.
For example:
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
See, it doesn’t matter whether the first operand is a string or the second one.
Here’s a more complex example:
alert(2 + 2 + '1' ); // "41" and not "221"
Here, operators work one after another. The first + sums two numbers, so it returns 4, then the
next + adds the string 1 to it, so it’s like 4 + '1' = '41'.
alert('1' + 2 + 2); // "122" and not "14"
Here, the first operand is a string, the compiler treats the other two operands as strings too.
The 2 gets concatenated to '1', so it’s like '1' + 2 = "12" and "12" + 2 = "122".
The binary + is the only operator that supports strings in such a way. Other arithmetic
operators work only with numbers and always convert their operands to numbers.
Here’s the demo for subtraction and division:
alert( 6 - '2' ); // 4, converts '2' to a number
alert( '6' / '2' ); // 3, converts both operands to numbers

Numeric conversion, unary +


The plus + exists in two forms: the binary form that we used above and the unary form.
The unary plus or, in other words, the plus operator + applied to a single value, doesn’t do
anything to numbers. But if the operand is not a number, the unary plus converts it into a
number.
For example:
// No effect on numbers
let x = 1;
alert( +x ); // 1

let y = -2;
alert( +y ); // -2

// Converts non-numbers
alert( +true ); // 1
alert( +"" ); // 0
It actually does the same thing as Number(...), but is shorter.
The need to convert strings to numbers arises very often. For example, if we are getting values
from HTML form fields, they are usually strings. What if we want to sum them?
The binary plus would add them as strings:
let apples = "2";
let oranges = "3";

alert( apples + oranges ); // "23", the binary plus concatenates strings


If we want to treat them as numbers, we need to convert and then sum them:
let apples = "2";
let oranges = "3";

// both values converted to numbers before the binary plus


alert( +apples + +oranges ); // 5

// the longer variant


// alert( Number(apples) + Number(oranges) ); // 5
From a mathematician’s standpoint, the abundance of pluses may seem strange. But from a
programmer’s standpoint, there’s nothing special: unary pluses are applied first, they convert
strings to numbers, and then the binary plus sums them up.
Why are unary pluses applied to values before the binary ones? As we’re going to see, that’s
because of their higher precedence.

Operator precedence - Operator precedence


If an expression has more than one operator, the execution order is defined by their
precedence, or, in other words, the default priority order of operators.
From school, we all know that the multiplication in the expression 1 + 2 * 2 should be
calculated before the addition. That’s exactly the precedence thing. The multiplication is said to
have higher precedence than the addition.
Parentheses override any precedence, so if we’re not satisfied with the default order, we can
use them to change it. For example, write (1 + 2) * 2.
There are many operators in JavaScript. Every operator has a corresponding precedence
number. The one with the larger number executes first. If the precedence is the same, the
execution order is from left to right.
Here’s an extract from the precedence table :
Precedence Name Sign
… … …
17 unary plus +
17 unary negation -
16 exponentiation **
15 multiplication *
15 division /
13 addition +
13 subtraction -
… … …
3 assignment =
… … …
(note that unary operators are higher than corresponding binary ones)
As we can see, the “unary plus” has a priority of 17 which is higher than the 13 of “addition”
(binary plus). That’s why, in the expression "+apples + +oranges", unary pluses work before
the addition.

Let's look at the last example from above, assuming that num2 holds the value 50 and num1
holds the value 10 (as originally stated above):
num2 + num1 / 8 + 2;
As a human being, you may read this as "50 plus 10 equals 60", then "8 plus 2 equals 10", and
finally "60 divided by 10 equals 6".
But the browser does "10 divided by 8 equals 1.25", then "50 plus 1.25 plus 2 equals 53.25".
This is because of operator precedence — some operators are applied before others when
calculating the result of a calculation (referred to as an expression, in programming).
Operator precedence in JavaScript is the same as is taught in math classes in school —
Multiply and divide are always done first, then add and subtract (the calculation is always
evaluated from left to right).
If you want to override operator precedence, you can put parentheses round the parts that
you want to be explicitly dealt with first. So to get a result of 6, we could do this:
(num2 + num1) / (8 + 2);

Assignment operators - Assignment operator =


Assignment operators are operators that assign a value to a variable. We have already
used the most basic one, =, loads of times — it assigns the variable on the left the value
stated on the right:
let x = 3; // x contains the value 3
let y = 4; // y contains the value 4
x = y; // x now contains the same value y contains, 4
But there are some more complex types, which provide useful shortcuts to keep your code
neater and more efficient. The most common are listed below:
Oper Name Purpose Exampl Shortcut for
ator e

+= Addition Adds the value on the right to the variable x += 4; x = x + 4;


assignment value on the left, then returns the new
variable value

-= Subtraction Subtracts the value on the right from the x -= 3; x = x - 3;


assignment variable value on the left, and returns the
new variable value

*= Multiplicati Multiplies the variable value on the left by x *= 3; x = x * 3;


on the value on the right, and returns the new
assignment variable value

/= Division Divides the variable value on the left by x /= 5; x = x / 5;


assignment the value on the right, and returns the new
variable value

Note that you can quite happily use other variables on the right hand side of each
expression, for example:
let x = 3; // x contains the value 3
let y = 4; // y contains the value 4
x *= y; // x now contains the value 12
Note: There are lots of other assignment operators available, but these are the
basic ones you should learn now.

Let’s note that an assignment = is also an operator. It is listed in the precedence table with a
very low priority of 3.
That’s why, when we assign a variable, like x = 2 * 2 + 1, the calculations are done first and
then the = is evaluated, storing the result in x.
let x = 2 * 2 + 1;
alert( x ); // 5

Assignment operator = returns a value


The fact of = being an operator, not a “magical” language construct has an interesting
implication.
All operators in JavaScript return a value. That’s obvious for + and -, but also true for =.
The call x = value writes the value into x and then returns it.
Here’s a demo that uses an assignment as part of a more complex expression:
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
alert( a ); // 3
alert( c ); // 0
In the example above, the result of the expression (a = b + 1) is the value that was assigned
to a (that is 3). It is then used for further evaluations.
We should understand how it works, because sometimes we see it in JavaScript libraries.
Although, please don’t write the code like that. Such tricks definitely don’t make code clearer or
readable.

Chaining assignments
Another interesting feature is the ability to chain assignments:
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
Chained assignments evaluate from right to left. First, the rightmost expression 2 + 2 is
evaluated and then assigned to the variables on the left: c, b and a. At the end, all the variables
share a single value.
Once again, for the purposes of readability it’s better to split such code into few lines:
c = 2 + 2;
b = c;
a = c;
That’s easier to read, especially when eye-scanning the code fast.

Modify-in-place
We often need to apply an operator to a variable and store the new result in that same variable.
For example:
let n = 2;
n = n + 5;
n = n * 2;
This notation can be shortened using the operators += and *=:
let n = 2;
n += 5; // now n = 7 (same as n = n + 5)
n *= 2; // now n = 14 (same as n = n * 2)
alert( n ); // 14
Short “modify-and-assign” operators exist for all arithmetical and bitwise operators: /=, -=, etc.
Such operators have the same precedence as a normal assignment, so they run after most
other calculations:
let n = 2;
n *= 3 + 5;
alert( n ); // 16 (right part evaluated first, same as n *= 8)

Increment/decrement operators

Increasing or decreasing a number by one is among the most common numerical operations.
So, there are special operators for it:
Increment ++ increases a variable by 1:
let counter = 2;
counter++; // works the same as counter = counter + 1, but is shorter
alert( counter ); // 3
Decrement -- decreases a variable by 1:
let counter = 2;
counter--; // works the same as counter = counter - 1, but is shorter
alert( counter ); // 1
Important:
Increment/decrement can only be applied to variables. Trying to use it on a value like 5++
will give an error.
The operators ++ and -- can be placed either before or after a variable.
●​ When the operator goes after the variable, it is in “postfix form”: counter++.
●​ The “prefix form” is when the operator goes before the variable: ++counter.
Both of these statements do the same thing: increase counter by 1.
Is there any difference? Yes, but we can only see it if we use the returned value of ++/--.
As we know, all operators return a value. Increment/decrement is no exception. The prefix form
returns the new value while the postfix form returns the old value (prior to
increment/decrement).
To see the difference, here’s an example:
let counter = 1;
let a = ++counter; // (*)
alert(a); // 2
In the line (*), the prefix form ++counter increments counter and returns the new value, 2. So,
the alert shows 2.
Now, let’s use the postfix form:
let counter = 1;
let a = counter++; // (*) changed ++counter to counter++
alert(a); // 1
In the line (*), the postfix form counter++ also increments counter but returns the old value
(prior to increment). So, the alert shows 1.
To summarize:
●​ If the result of increment/decrement is not used, there is no difference in which form to
use:
let counter = 0;
counter++;
++counter;
alert( counter ); // 2, the lines above did the same
●​ If we’d like to increase a value and immediately use the result of the operator, we need
the prefix form:
let counter = 0;
alert( ++counter ); // 1
●​ If we’d like to increment a value but use its previous value, we need the postfix form:
let counter = 0;
alert( counter++ ); // 0

Increment/decrement among other operators


The operators ++/-- can be used inside expressions as well. Their precedence is higher
than most other arithmetical operations.
For instance:
let counter = 1;
alert( 2 * ++counter ); // 4
Compare with:
let counter = 1;
alert( 2 * counter++ ); // 2, because counter++ returns the "old" value
Though technically okay, such notation usually makes code less readable. One line does
multiple things – not good.
While reading code, a fast “vertical” eye-scan can easily miss something like counter++ and
it won’t be obvious that the variable increased.
We advise a style of “one line – one action”:
let counter = 1;
alert( 2 * counter );
counter++;

Bitwise(bit a bit) operators (used rarely) - Bitwise operators


(MDN)
Bitwise operators treat arguments as 32-bit integer numbers and work on the level of their
binary representation.
These operators are not JavaScript-specific. They are supported in most programming
languages.
The list of operators:
●​ AND ( & )
●​ OR ( | )
●​ XOR ( ^ )
●​ NOT ( ~ )
●​ LEFT SHIFT ( << )
●​ RIGHT SHIFT ( >> )
●​ ZERO-FILL RIGHT SHIFT ( >>> )
These operators are used very rarely, when we need to fiddle with numbers on the very lowest
(bitwise) level. We won’t need these operators any time soon, as web development has little use
of them, but in some special areas, such as cryptography, they are useful. You can read the
Bitwise Operators chapter on MDN when a need arises.

Comma ,
The comma operator , is one of the rarest and most unusual operators. Sometimes, it’s used to
write shorter code, so we need to know it in order to understand what’s going on.
The comma operator allows us to evaluate several expressions, dividing them with a comma ,.
Each of them is evaluated but only the result of the last one is returned.
For example:
let a = (1 + 2, 3 + 4);
alert( a ); // 7 (the result of 3 + 4)
Here, the first expression 1 + 2 is evaluated and its result is thrown away. Then, 3 + 4 is
evaluated and returned as the result.

Comma has a very low precedence


Please note that the comma operator has very low precedence, lower than =, so
parentheses are important in the example above.
Without them: a = 1 + 2, 3 + 4 evaluates + first, summing the numbers into a = 3, 7,
then the assignment operator = assigns a = 3, and the rest is ignored.
It’s like (a = 1 + 2), 3 + 4.
Why do we need an operator that throws away everything except the last expression?
Sometimes, people use it in more complex constructs to put several actions in one line.
For example:
// three operations in one line
for (a = 1, b = 3, c = a * b; a < 10; a++) {
...
}
Such tricks are used in many JavaScript frameworks. That’s why we’re mentioning them. But
usually they don’t improve code readability so we should think well before using them.

Comma operator
,
The comma operator allows multiple expressions to be evaluated in a single
statement and returns the result of the last expression.
Tasks
The postfix and prefix forms
importance: 5
What are the final values of all variables a, b, c and d after the code below?
let a = 1, b = 1;

let c = ++a; // ?
let d = b++; // ?
solution
The answer is:
●​ a = 2
●​ b = 2
●​ c = 2
●​ d = 1
let a = 1, b = 1;

alert( ++a ); // 2, prefix form returns the new value


alert( b++ ); // 1, postfix form returns the old value

alert( a ); // 2, incremented once


alert( b ); // 2, incremented once
Assignment result
importance: 3
What are the values of a and x after the code below?
let a = 2;

let x = 1 + (a *= 2);
solution
The answer is:
●​ a = 4 (multiplied by 2)
●​ x = 5 (calculated as 1 + 4)
Type conversions
importance: 5
What are results of these expressions?
"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
7 / 0
" -9 " + 5
" -9 " - 5
null + 1
undefined + 1
" \t \n" - 2
Think well, write down and then compare with the answer.
solution
"" + 1 + 0 = "10" // (1)
"" - 1 + 0 = -1 // (2)
true + false = 1
6 / "3" = 2
"2" * "3" = 6
4 + 5 + "px" = "9px"
"$" + 4 + 5 = "$45"
"4" - 2 = 2
"4px" - 2 = NaN
7 / 0 = Infinity
" -9 " + 5 = " -9 5" // (3)
" -9 " - 5 = -14 // (4)
null + 1 = 1 // (5)
undefined + 1 = NaN // (6)
" \t \n" - 2 = -2 // (7)
1.​ The addition with a string "" + 1 converts 1 to a string: "" + 1 = "1", and then
we have "1" + 0, the same rule is applied.
2.​ The subtraction - (like most math operations) only works with numbers, it converts
an empty string "" to 0.
3.​ The addition with a string appends the number 5 to the string.
4.​ The subtraction always converts to numbers, so it makes " -9 " a number -9
(ignoring spaces around it).
5.​ null becomes 0 after the numeric conversion.
6.​ undefined becomes NaN after the numeric conversion.
7.​ Space characters, are trimmed off string start and end when a string is converted to
a number. Here the whole string consists of space characters, such as \t, \n and a
“regular” space between them. So, similarly to an empty string, it becomes 0.
Fix the addition
importance: 5
Here’s a code that asks the user for two numbers and shows their sum.
It works incorrectly. The output in the example below is 12 (for default prompt values).
Why? Fix it. The result should be 3.
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);

alert(a + b); // 12
solution
The reason is that prompt returns user input as a string.
So variables have values "1" and "2" respectively.
let a = "1"; // prompt("First number?", 1);
let b = "2"; // prompt("Second number?", 2);

alert(a + b); // 12
What we should do is to convert strings to numbers before +. For example, using Number()
or prepending them with +.
For example, right before prompt:
let a = +prompt("First number?", 1);
let b = +prompt("Second number?", 2);

alert(a + b); // 3
Or in the alert:
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);

alert(+a + +b); // 3
Using both unary and binary + in the latest code. Looks funny, doesn’t it?

Equality comparisons and sameness -


Comparisons
There are four equality algorithms in ES2015:
●​ Abstract Equality Comparison (==)
●​ Strict Equality Comparison (===): used by [Link],
[Link], and case-matching
●​ SameValueZero: used by %TypedArray% and ArrayBuffer constructors, as well as
Map and Set operations, and also [Link] and
[Link] since ES2016
●​ SameValue: used in all other places

JavaScript provides three different value-comparison operations:


●​ === - Strict Equality Comparison ("strict equality", "identity", "triple equals")
●​ == - Abstract Equality Comparison ("loose equality", "double equals")
●​ [Link] provides SameValue (new in ES2015).

Which operation you choose depends on what sort of comparison you are looking to
perform. Briefly:
●​ double equals (==) will perform a type conversion when comparing two things, and
will handle NaN, -0, and +0 specially to conform to IEEE 754 (so NaN != NaN, and -0
== +0);
●​ triple equals (===) will do the same comparison as double equals (including the
special handling for NaN, -0, and +0) but without type conversion; if the types differ,
false is returned.
●​ [Link] does no type conversion and no special handling for NaN, -0, and +0
(giving it the same behavior as === except on those special numeric values).
Note that the distinction between these all have to do with their handling of primitives; none
of them compares whether the parameters are conceptually similar in structure. For any
non-primitive objects x and y which have the same structure but are distinct objects
themselves, all of the above forms will evaluate to false.

We know many comparison operators from maths.


In JavaScript they are written like this:
●​ Greater/less than: a > b, a < b.
●​ Greater/less than or equals: a >= b, a <= b.
●​ Equals: a == b, please note the double equality sign == means the equality test, while a
single one a = b means an assignment.
●​ Not equals. In maths the notation is ≠, but in JavaScript it’s written as a != b.
At the end you’ll find a good recipe to avoid “JavaScript quirks”-related issues.

Boolean is the result


All comparison operators return a boolean value:
●​ true – means “yes”, “correct” or “the truth”.
●​ false – means “no”, “wrong” or “not the truth”.
For example:
alert( 2 > 1 ); // true (correct)
alert( 2 == 1 ); // false (wrong)
alert( 2 != 1 ); // true (correct)
A comparison result can be assigned to a variable, just like any value:
let result = 5 > 4; // assign the result of the comparison
alert( result ); // true

Strict equality using === - Strict equality (===)


Strict equality compares two values for equality. Neither value is implicitly converted to
some other value before being compared. If the values have different types, the values are
considered unequal. If the values have the same type, are not numbers, and have the
same value, they're considered equal. Finally, if both values are numbers, they're
considered equal if they're both not NaN and are the same value, or if one is +0 and one is
-0.
var num = 0;
var obj = new String('0');
var str = '0';
[Link](num === num); // true
[Link](obj === obj); // true
[Link](str === str); // true
[Link](num === obj); // false
[Link](num === str); // false
[Link](obj === str); // false
[Link](null === undefined); // false
[Link](obj === null); // false
[Link](obj === undefined); // false

Strict equality is almost always the correct comparison operation to use. For all values
except numbers, it uses the obvious semantics: a value is only equal to itself. For
numbers it uses slightly different semantics to gloss over two different edge cases.
The first is that floating point zero is either positively or negatively signed. This is useful in
representing certain mathematical solutions, but as most situations don't care about the
difference between +0 and -0, strict equality treats them as the same value.
The second is that floating point includes the concept of a not-a-number value, NaN, to
represent the solution to certain ill-defined mathematical problems: negative infinity
added to positive infinity, for example. Strict equality treats NaN as unequal to every other
value -- including itself. (The only case in which (x !== x) is true is when x is NaN.)

A strict equality operator === checks the equality without type conversion.
In other words, if a and b are of different types, then a === b immediately returns false
without an attempt to convert them.
Let’s try it:
alert( 0 === false ); // false, because the types are different
The strict equality operator is a bit longer to write, but makes it obvious what’s going on and
leaves less room for errors.

Tests whether the left and right values are identical to one another

Loose equality using ==


Loose equality compares two values for equality, after converting both values to a
common type. After conversions (one or both sides may undergo conversions), the final
equality comparison is performed exactly as === performs it. Loose equality is symmetric:
A == B always has identical semantics to B == A for any values of A and B (except for the
order of applied conversions).
The equality comparison is performed as follows for operands of the various types:
Operand B

Undefined Null Number String Boolean Object

Ope Undefined true true false false false false


ran
dA
Null true true false false false false

Number false false A === B A === A === A ==


ToNumber(B) ToNumber(B) ToPrimitive(B)

String false false ToNumber( A === B ToNumber(A) A ==


A) === B === ToPrimitive(B)
ToNumber(B)

Boolean false false ToNumber( ToNumber(A) A === B ToNumber(A) ==


A) === B === ToPrimitive(B)
ToNumber(B)

Object false false ToPrimiti ToPrimitive ToPrimitive( A === B


ve(A) == (A) == B A) ==
B ToNumber(B)
In the above table, ToNumber(A) attempts to convert its argument to a number before
comparison. Its behavior is equivalent to +A (the unary + operator). ToPrimitive(A)
attempts to convert its object argument to a primitive value, by attempting to invoke
varying sequences of [Link] and [Link] methods on A.
Traditionally, and according to ECMAScript, all objects are loosely unequal to undefined and
null. But most browsers permit a very narrow class of objects (specifically, the
[Link] object for any page), in some contexts, to act as if they emulate the value
undefined. Loose equality is one such context: null == A and undefined == A evaluate
to true if, and only if, A is an object that emulates undefined. In all other cases an object is
never loosely equal to undefined or null.
var num = 0;
var obj = new String('0');
var str = '0';

[Link](num == num); // true


[Link](obj == obj); // true
[Link](str == str); // true

[Link](num == obj); // true


[Link](num == str); // true
[Link](obj == str); // true
[Link](null == undefined); // true

// both false, except in rare cases


[Link](obj == null);
[Link](obj == undefined);

In most cases, using loose equality is discouraged. The result of a comparison using strict
equality is easier to predict, and may evaluate more quickly due to the lack of type
coercion.

A regular equality check == has a problem. It cannot differentiate 0 from false:


alert( 0 == false ); // true
The same thing happens with an empty string:
alert( '' == false ); // true
This happens because operands of different types are converted to numbers by the equality
operator ==. An empty string, just like false, becomes a zero.
What to do if we’d like to differentiate 0 from false?

Comparison of different types


When comparing values of different types, JavaScript converts the values to numbers.
For example:
alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1
For boolean values, true becomes 1 and false becomes 0.
For example:
alert( true == 1 ); // true
alert( false == 0 ); // true

Weird consequences
It is possible that at the same time:
●​ Two values are equal.
●​ One of them is true as a boolean and the other one is false as a boolean.
For example:
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
From JavaScript’s standpoint, this result is quite normal. An equality check converts values
using the numeric conversion (hence "0" becomes 0), while the explicit Boolean
conversion uses another set of rules.

Strict-non-equality (!==)
There is also a “strict non-equality” operator !== analogous to !=.

Tests whether the left and right values are not identical to one another

Note: You may see some people using == and != in their tests for equality and non-equality.
These are valid operators in JavaScript, but they differ from ===/!==. The former versions test
whether the values are the same but not whether the values' datatypes are the same. The
latter, strict versions test the equality of both the values and their datatypes. The strict
versions tend to result in fewer errors, so we recommend you use them.

If you try entering some of these values in a console, you'll see that they all return true/false
values — those booleans we mentioned in the last article. These are very useful, as they allow
us to make decisions in our code, and they are used every time we want to make a choice of
some kind. For example, booleans can be used to:
●​ Display the correct text label on a button depending on whether a feature is turned on or
off
●​ Display a game over message if a game is over or a victory message if the game has
been won
●​ Display the correct seasonal greeting depending what holiday season it is
●​ Zoom a map in or out depending on what zoom level is selected
We'll look at how to code such logic when we look at conditional statements in a future article.
For now, let's look at a quick example:
<button>Start machine</button>
<p>The machine is stopped.</p>

const btn = [Link]('button');


const txt = [Link]('p');

[Link]('click', updateBtn);

function updateBtn() {
if ([Link] === 'Start machine') {
[Link] = 'Stop machine';
[Link] = 'The machine has started!';
} else {
[Link] = 'Start machine';
[Link] = 'The machine is stopped.';
}
}
Open in new window
You can see the equality operator being used just inside the updateBtn() function. In this case,
we are not testing if two mathematical expressions have the same value — we are testing
whether the text content of a button contains a certain string — but it is still the same principle at
work. If the button is currently saying "Start machine" when it is pressed, we change its label to
"Stop machine", and update the label as appropriate. If the button is currently saying "Stop
machine" when it is pressed, we swap the display back again.
Note: Such a control that swaps between two states is generally referred to as a toggle. It
toggles between one state and another — light on, light off, etc.

Same-value equality ([Link])


Same-value equality addresses a final use case: determining whether two values are
functionally identical in all contexts. (This use case demonstrates an instance of the Liskov
substitution principle.) One instance occurs when an attempt is made to mutate an
immutable property:
// Add an immutable NEGATIVE_ZERO property to the Number constructor.
[Link](Number, 'NEGATIVE_ZERO',
{ value: -0, writable: false, configurable: false,
enumerable: false });

function attemptMutation(v) {
[Link](Number, 'NEGATIVE_ZERO', { value: v });
}

[Link] will throw an exception when attempting to change an immutable


property, but it does nothing if no actual change is requested. If v is -0, no change has
been requested, and no error will be thrown. Internally, when an immutable property is
redefined, the newly-specified value is compared against the current value using
same-value equality.
Same-value equality is provided by the [Link] method.

Same-value-zero equality
Similar to same-value equality, but +0 and -0 are considered equal.

Abstract equality, strict equality, and same value in the


specification
In ES5, the comparison performed by == is described in Section 11.9.3, The Abstract
Equality Algorithm. The === comparison is 11.9.6, The Strict Equality Algorithm. (Go look
at these. They're brief and readable. Hint: read the strict equality algorithm first.)
ES5 also describes, in Section 9.12, The SameValue Algorithm for use internally by the JS
engine. It's largely the same as the Strict Equality Algorithm, except that [Link] and 9.12.4
differ in handling Numbers. ES2015 proposes to expose this algorithm through [Link].
We can see that with double and triple equals, with the exception of doing a type check
upfront in [Link], the Strict Equality Algorithm is a subset of the Abstract Equality
Algorithm, because [Link]–7 correspond to [Link].a–f.

A model for understanding equality comparisons?


Prior to ES2015, you might have said of double equals and triple equals that one is an
"enhanced" version of the other. For example, someone might say that double equals is an
extended version of triple equals, because the former does everything that the latter does, but
with type conversion on its operands. E.g., 6 == "6". (Alternatively, someone might say that
double equals is the baseline, and triple equals is an enhanced version, because it requires the
two operands to be the same type, so it adds an extra constraint. Which one is the better
model for understanding depends on how you choose to view things.)
However, this way of thinking about the built-in sameness operators is not a model that can be
stretched to allow a place for ES2015's [Link] on this "spectrum". [Link] isn't "looser"
than double equals or "stricter" than triple equals, nor does it fit somewhere in between (i.e.,
being both stricter than double equals, but looser than triple equals). We can see from the
sameness comparisons table below that this is due to the way that [Link] handles NaN.
Notice that if [Link](NaN, NaN) evaluated to false, we could say that it fits on the
loose/strict spectrum as an even stricter form of triple equals, one that distinguishes between -0
and +0. The NaN handling means this is untrue, however. Unfortunately, [Link] has to be
thought of in terms of its specific characteristics, rather than its looseness or strictness
with regard to the equality operators.
x y

undefin undefin t t t t
ed ed

null null t t t t

true true t t t t

false false t t t t

'foo' 'foo' t t t t

0 0 t t t t

+0 -0 t t f t

+0 0 t t t t
-0 0 t t f t

0n -0n t t t t

0 false t f f f

"" false t f f f

"" 0 t f f f

'0' 0 t f f f

'17' 17 t f f f

[1, 2] '1,2' t f f f

new 'foo' t f f f
String(
'foo')

null undefin t f f f
ed

null false f f f f

undefin false f f f f
ed

{ foo: { foo: f f f f
'bar' } 'bar' }

new new f f f f
String( String(
'foo') 'foo')

0 null f f f f

0 NaN f f f f
'foo' NaN f f f f

NaN NaN f f t t

When to use [Link] versus triple equals


In general, the only time [Link]'s special behavior towards zeros is likely to be of interest
is in the pursuit of certain meta-programming schemes, especially regarding property
descriptors, when it is desirable for your work to mirror some of the characteristics of
[Link]. If your use case does not require this, it is suggested to avoid
[Link] and use === instead. Even if your requirements involve having comparisons
between two NaN values evaluate to true, generally it is easier to special-case the NaN
checks (using the isNaN method available from previous versions of ECMAScript) than it is to
work out how surrounding computations might affect the sign of any zeros you encounter in your
comparison.
Here's a non-exhaustive list of built-in methods and operators that might cause a distinction
between -0 and +0 to manifest itself in your code:
- (unary negation)
let stoppingForce = [Link] * -[Link];
If [Link] is 0 (or computes to 0), a -0 is introduced at that place and propagates out
into stoppingForce.
Math.atan2
[Link]
[Link]
[Link]
In some cases,it's possible for a -0 to be introduced into an expression as a return value of
these methods even when no -0 exists as one of the parameters. For example, using
[Link] to raise -Infinity to the power of any negative, odd exponent evaluates to -0.
Refer to the documentation for the individual methods.
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
It's possible to get a -0 return value out of these methods in some cases where a -0 exists
as one of the parameters. E.g., [Link](-0, +0) evaluates to -0. Refer to the
documentation for the individual methods.
~
<<
>>
Each of these operators uses the ToInt32 algorithm internally. Since there is only one
representation for 0 in the internal 32-bit integer type, -0 will not survive a round trip after an
inverse operation. E.g., both [Link](~~(-0), -0) and [Link](-0 << 2 >> 2,
-0) evaluate to false.
Relying on [Link] when the signedness of zeros is not taken into account can be
hazardous. Of course, when the intent is to distinguish between -0 and +0, it does exactly
what's desired.
Caveat: [Link] and NaN
The [Link] specification treats all instances of NaN as the same object. However, since
typed arrays are available, we can have distinct instances, which don't behave identically in all
contexts. For example:
var f2b = x => new Uint8Array(new Float64Array([x]).buffer);
var b2f = x => new Float64Array([Link])[0];
var n = f2b(NaN);
n[0] = 1;
var nan2 = b2f(n);
nan2;
// > NaN
[Link](nan2, NaN);
// > true
f2b(NaN);
// > Uint8Array(8) [0, 0, 0, 0, 0, 0, 248,127)
f2b(nan2);
// > Uint8Array(8) [1, 0, 0, 0, 0, 0, 248,127)

Comparison with null and undefined


There’s a non-intuitive behavior when null or undefined are compared to other values.

For a strict equality check ===


These values are different because each of them is a different type.
alert( null === undefined ); // false

For a non-strict check ==


There’s a special rule. These two are a “sweet couple”: they equal each other (in the sense of
==), but not any other value.
alert( null == undefined ); // true

For maths and other comparisons < > <= >=


null/undefined are converted to numbers: null becomes 0, while undefined becomes NaN.

Strange result: null vs 0


Let’s compare null with a zero:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
Mathematically, that’s strange. The last result states that "null is greater than or equal to
zero", so in one of the comparisons above it must be true, but they are both false.
The reason is that an equality check == and comparisons > < >= <= work differently.
Comparisons convert null to a number, treating it as 0. That’s why (3) null >= 0 is true and
(1) null > 0 is false.
On the other hand, the equality check == for undefined and null is defined such that, without
any conversions, they equal each other and don’t equal anything else. That’s why (2) null ==
0 is false.
An incomparable undefined
The value undefined shouldn’t be compared to other values:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
Why does it dislike zero so much? Always false!
We get these results because:
●​ Comparisons (1) and (2) return false because undefined gets converted to NaN and
NaN is a special numeric value that returns false for all comparisons.
●​ The equality check (3) returns false because undefined only equals null,
undefined, and no other value.

Avoid problems
Why did we go over these examples? Should we remember these peculiarities all the time? Well,
not really. Actually, these tricky things will gradually become familiar over time, but there’s a
solid way to avoid problems with them:
●​ Treat any comparison with undefined/null except the strict equality === with
exceptional care.
●​ Don’t use comparisons >= > < <= with a variable that may be null/undefined, unless
you’re really sure of what you’re doing. If a variable can have these values, check for
them separately.

Summary
●​ Comparison operators return a boolean value.
●​ Strings are compared letter-by-letter in the “dictionary” order.
●​ When values of different types are compared, they get converted to numbers (with the
exclusion of a strict equality check).
●​ The values null and undefined equal == each other and do not equal any other value.
●​ Be careful when using comparisons like > or < with variables that can occasionally be
null/undefined. Checking for null/undefined separately is a good idea.

Tasks
Comparisons
importance: 5
What will be the result for these expressions?
5 > 4
"apple" > "pineapple"
"2" > "12"
undefined == null
undefined === null
null == "\n0\n"
null === +"\n0\n"
solution
5 > 4 → true
"apple" > "pineapple" → false
"2" > "12" → true
undefined == null → true
undefined === null → false
null == "\n0\n" → false
null === +"\n0\n" → false
Some of the reasons:
1.​ Obviously, true.
2.​ Dictionary comparison, hence false. "a" is smaller than "p".
3.​ Again, dictionary comparison, first char "2" is greater than the first char "1".
4.​ Values null and undefined equal each other only.
5.​ Strict equality is strict. Different types from both sides lead to false.
6.​ Similar to (4), null only equals undefined.
7.​ Strict equality of different types.

Logical operators
There are three logical operators in JavaScript: || (OR), && (AND), ! (NOT).
Although they are called “logical”, they can be applied to values of any type, not only boolean.
Their result can also be of any type.
Let’s see the details.

|| (OR)
The “OR” operator is represented with two vertical line symbols:
result = a || b;
In classical programming, the logical OR is meant to manipulate boolean values only. If any of
its arguments are true, it returns true, otherwise it returns false.
In JavaScript, the operator is a little bit trickier and more powerful. But first, let’s see what
happens with boolean values.
There are four possible logical combinations:
alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false
As we can see, the result is always true except for the case when both operands are false.
If an operand is not a boolean, it’s converted to a boolean for the evaluation.
For instance, the number 1 is treated as true, the number 0 as false:
if (1 || 0) { // works just like if( true || false )
alert( 'truthy!' );
}
Most of the time, OR || is used in an if statement to test if any of the given conditions is true.
For example:
let hour = 9;
if (hour < 10 || hour > 18) {
alert( 'The office is closed.' );
}
We can pass more conditions:
let hour = 12;
let isWeekend = true;
if (hour < 10 || hour > 18 || isWeekend) {
alert( 'The office is closed.' ); // it is the weekend
}

OR “||” finds the first truthy value


The logic described above is somewhat classical. Now, let’s bring in the “extra” features of
JavaScript.
The extended algorithm works as follows.
Given multiple OR’ed values:
result = value1 || value2 || value3;
The OR || operator does the following:
●​ Evaluates operands from left to right.
●​ For each operand, converts it to boolean. If the result is true, stops and returns the
original value of that operand.
●​ If all operands have been evaluated (i.e. all were false), returns the last operand.
A value is returned in its original form, without the conversion.

In other words, a chain of OR || returns the first truthy value or the last one if no truthy value is
found.
For instance:
alert( 1 || 0 ); // 1 (1 is truthy)
alert( null || 1 ); // 1 (1 is the first truthy value)
alert( null || 0 || 1 ); // 1 (the first truthy value)
alert( undefined || null || 0 ); // 0 (all falsy, returns the last value)
This leads to some interesting usage compared to a “pure, classical, boolean-only OR”.

1.​ Getting the first truthy value from a list of variables or expressions.​
For instance, we have firstName, lastName and nickName variables, all optional (i.e.
can be undefined or have falsy values).​
Let’s use OR || to choose the one that has the data and show it (or "Anonymous" if
nothing set):
let firstName = "";
let lastName = "";
let nickName = "SuperCoder";
alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
If all variables were falsy, "Anonymous" would show up.

2.​ Short-circuit evaluation.​


Another feature of OR || operator is the so-called “short-circuit” evaluation.​
It means that || processes its arguments until the first truthy value is reached, and then
the value is returned immediately, without even touching the other argument.​
That importance of this feature becomes obvious if an operand isn’t just a value, but an
expression with a side effect, such as a variable assignment or a function call.​
In the example below, only the second message is printed:
true || alert("not printed");
false || alert("printed");
In the first line, the OR || operator stops the evaluation immediately upon seeing true, so the
alert isn’t run.​
Sometimes, people use this feature to execute commands only if the condition on the left part is
falsy.

Bitwise OR (|) Operator


The bitwise OR operator (|) returns a 1 in each bit position for which the corresponding
bits of either or both operands are 1s.

Syntax
a | b

Description
The operands are converted to 32-bit integers and expressed by a series of bits (zeroes
and ones). Numbers with more than 32 bits get their most significant bits discarded. For
example, the following integer with more than 32 bits will be converted to a 32 bit integer:
Before: 11100110111110100000000000000110000000000001
After: 10100000000000000110000000000001
Each bit in the first operand is paired with the corresponding bit in the second operand:
first bit to first bit, second bit to second bit, and so on.
The operator is applied to each pair of bits, and the result is constructed bitwise.
The truth table for the OR operation is:
a b a OR b

0 0 0

0 1 1

1 0 1

1 1 1
. 9 (base 10) = 00000000000000000000000000001001 (base 2)
14 (base 10) = 00000000000000000000000000001110 (base 2)
--------------------------------
14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10)

Bitwise ORing any number x with 0 yields x.

Examples
Using bitwise OR
// 9 (00000000000000000000000000001001)
// 14 (00000000000000000000000000001110)
14 | 9;
// 15 (00000000000000000000000000001111)

&& (AND)
The AND operator is represented with two ampersands &&:
result = a && b;
In classical programming, AND returns true if both operands are truthy and false otherwise:
alert( true && true ); // true
alert( false && true ); // false
alert( true && false ); // false
alert( false && false ); // false
An example with if:
let hour = 12;
let minute = 30;

if (hour == 12 && minute == 30) {


alert( 'The time is 12:30' );
}
Just as with OR, any value is allowed as an operand of AND:
if (1 && 0) { // evaluated as true && false
alert( "won't work, because the result is falsy" );
}

AND “&&” finds the first falsy value


Given multiple AND’ed values:
result = value1 && value2 && value3;
The AND && operator does the following:
●​ Evaluates operands from left to right.
●​ For each operand, converts it to a boolean. If the result is false, stops and returns the
original value of that operand.
●​ If all operands have been evaluated (i.e. all were truthy), returns the last operand.
In other words, AND returns the first falsy value or the last value if none were found.
The rules above are similar to OR. The difference is that AND returns the first falsy value while
OR returns the first truthy one.
Examples:
// if the first operand is truthy,
// AND returns the second operand:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// if the first operand is falsy,


// AND returns it. The second operand is ignored
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
We can also pass several values in a row. See how the first falsy one is returned:
alert( 1 && 2 && null && 3 ); // null
When all values are truthy, the last value is returned:
alert( 1 && 2 && 3 ); // 3, the last one

Precedence of AND && is higher than OR ||


The precedence of AND && operator is higher than OR ||.
So the code a && b || c && d is essentially the same as if the && expressions were in
parentheses: (a && b) || (c && d).
Don’t replace if with || or &&
Sometimes, people use the AND && operator as a "shorter way to write if".
For instance:
let x = 1;
(x > 0) && alert( 'Greater than zero!' );
The action in the right part of && would execute only if the evaluation reaches it. That is,
only if (x > 0) is true.
So we basically have an analogue for:
let x = 1;
if (x > 0) alert( 'Greater than zero!' );
Although, the variant with && appears shorter, if is more obvious and tends to be a little bit
more readable. So we recommend using every construct for its purpose: use if if we want
if and use && if we want AND.

! (NOT)
The boolean NOT operator is represented with an exclamation sign !.
The syntax is pretty simple:
result = !value;
The operator accepts a single argument and does the following:
1.​ Converts the operand to boolean type: true/false.
2.​ Returns the inverse value.
For instance:
alert( !true ); // false
alert( !0 ); // true
A double NOT !! is sometimes used for converting a value to boolean type:
alert( !!"non-empty string" ); // true
alert( !!null ); // false
That is, the first NOT converts the value to boolean and returns the inverse, and the second NOT
inverses it again. In the end, we have a plain value-to-boolean conversion.
There’s a little more verbose way to do the same thing – a built-in Boolean function:
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
The precedence of NOT ! is the highest of all logical operators, so it always executes first,
before && or ||.

Truthy / Falsy
A truthy or falsy value is a value that is being casted into a boolean when evaluated in a boolean
context. An example of boolean context would be the evaluation of an if condition:

Every value will be casted to true unless they are equal to:​
false
0
“”(empty string)
null
undefined
NaN
examples of boolean context:
if condition evaluation​
if (myVar) {}

myVar can be any first-class citizen (variable, function, boolean) but it will be casted into a boolean
because it's evaluated in a boolean context.​

After logical NOT ! operator​


This operator returns false if its single operand can be converted to true; otherwise, returns true.
!0 // true -- 0 is falsy so it returns true
!!0 // false -- 0 is falsy so !0 returns true so !(!0) returns false
!!"" // false -- empty string is falsy so NOT (NOT false) equals false

With the Boolean object constructor​
new Boolean(0) // false​
new Boolean(1) // true

In a ternary evaluation​
myVar ? "truthy" : "falsy"​
myVar is evaluated in a boolean context.

Be careful when comparing 2 values. The object values (that should be cast to true) is not being casted
to Boolean but it forced to convert into a primitive value one using ToPrimitives specification.
Internally, when an object is compared to Boolean value like [] == true, it does [].toString() == true so…​
let a = [] == true // a is false since [].toString() give "" back.​
let b = [1] == true // b is true since [1].toString() give "1" back.​
let c = [2] == true // c is false since [2].toString() give "2" back.

Tasks
What's the result of OR?
importance: 5
What is the code below going to output?
alert( null || 2 || undefined );
solution
The answer is 2, that’s the first truthy value.
alert( null || 2 || undefined );
What's the result of OR'ed alerts?
importance: 3
What will the code below output?
alert( alert(1) || 2 || alert(3) );
solution
The answer: first 1, then 2.
alert( alert(1) || 2 || alert(3) );
The call to alert does not return a value. Or, in other words, it returns undefined.
1.​ The first OR || evaluates its left operand alert(1). That shows the first message
with 1.
2.​ The alert returns undefined, so OR goes on to the second operand searching for
a truthy value.
3.​ The second operand 2 is truthy, so the execution is halted, 2 is returned and then
shown by the outer alert.
There will be no 3, because the evaluation does not reach alert(3).
What is the result of AND?
importance: 5
What is this code going to show?
alert( 1 && null && 2 );
solution
The answer: null, because it’s the first falsy value from the list.
alert( 1 && null && 2 );
What is the result of AND'ed alerts?
importance: 3
What will this code show?
alert( alert(1) && alert(2) );
solution
The answer: 1, and then undefined.
alert( alert(1) && alert(2) );
The call to alert returns undefined (it just shows a message, so there’s no meaningful
return).
Because of that, && evaluates the left operand (outputs 1), and immediately stops, because
undefined is a falsy value. And && looks for a falsy value and returns it, so it’s done.
The result of OR AND OR
importance: 5
What will the result be?
alert( null || 2 && 3 || 4 );
solution
The answer: 3.
alert( null || 2 && 3 || 4 );
The precedence of AND && is higher than ||, so it executes first.
The result of 2 && 3 = 3, so the expression becomes:
null || 3 || 4
Now the result is the first truthy value: 3.
Check the range between
importance: 3
Write an if condition to check that age is between 14 and 90 inclusively.
“Inclusively” means that age can reach the edges 14 or 90.
solution
if (age >= 14 && age <= 90)
Check the range outside
importance: 3
Write an if condition to check that age is NOT between 14 and 90 inclusively.
Create two variants: the first one using NOT !, the second one – without it.
solution
The first variant:
if (!(age >= 14 && age <= 90))
The second variant:
if (age < 14 || age > 90)
A question about "if"
importance: 5
Which of these alerts are going to execute?
What will the results of the expressions be inside if(...)?
if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );
solution
The answer: the first and the third will execute.
Details:
// Runs.
// The result of -1 || 0 = -1, truthy
if (-1 || 0) alert( 'first' );

// Doesn't run
// -1 && 0 = 0, falsy
if (-1 && 0) alert( 'second' );

// Executes
// Operator && has a higher precedence than ||
// so -1 && 1 executes first, giving us the chain:
// null || -1 && 1 -> null || 1 -> 1
if (null || -1 && 1) alert( 'third' );
Check the login
importance: 3
Write the code which asks for a login with prompt.
If the visitor enters "Admin", then prompt for a password, if the input is an empty line or Esc –
show “Canceled”, if it’s another string – then show “I don’t know you”.
The password is checked as follows:
●​ If it equals “TheMaster”, then show “Welcome!”,
●​ Another string – show “Wrong password”,
●​ For an empty string or cancelled input, show “Canceled”
The schema:
Please use nested if blocks. Mind the overall readability of the code.
Hint: passing an empty input to a prompt returns an empty string ''. Pressing ESC during a
prompt returns null.
Run the demo
solution
let userName = prompt("Who's there?", '');

if (userName === 'Admin') {

let pass = prompt('Password?', '');

if (pass === 'TheMaster') {


alert( 'Welcome!' );
} else if (pass === '' || pass === null) {
alert( 'Canceled' );
} else {
alert( 'Wrong password' );
}

} else if (userName === '' || userName === null) {


alert( 'Canceled' );
} else {
alert( "I don't know you" );
}
Note the vertical indents inside the if blocks. They are technically not required, but make
the code more readable.

Nullish coalescing operator '??'


A recent addition
This is a recent addition to the language. Old browsers may need polyfills.
An expression is “defined” when it’s neither null nor undefined.
The nullish coalescing operator is written as two question marks ??.
The result of a ?? b is:
●​ if a is defined, then a,
●​ if a isn’t defined, then b.
In other words, ?? returns the first argument if it’s not null/undefined. Otherwise, the second
one.
The nullish coalescing operator isn’t anything completely new. It’s just a nice syntax to get the
first “defined” value of the two.
We can rewrite result = a ?? b using the operators that we already know, like this:
result = (a !== null && a !== undefined) ? a : b;
The common use case for ?? is to provide a default value for a potentially undefined variable.
For example, here we show Anonymous if user isn’t defined:
let user;
alert(user ?? "Anonymous"); // Anonymous
Of course, if user had any value except null/undefined, then we would see it instead:
let user = "John";
alert(user ?? "Anonymous"); // John
We can also use a sequence of ?? to select the first value from a list that isn’t
null/undefined.
Let’s say we have a user’s data in variables firstName, lastName or nickName. All of them may
be undefined if the user decided not to enter a value.
We’d like to display the user name using one of these variables or show “Anonymous” if all of
them are undefined.
Let’s use the ?? operator for that:
let firstName = null;
let lastName = null;
let nickName = "Supercoder";
// shows the first defined value:
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

Comparison with ||
The OR || operator can be used in the same way as ??, as it was described in the previous
chapter.
For example, in the code above we could replace ?? with || and still get the same result:
let firstName = null;
let lastName = null;
let nickName = "Supercoder";
// shows the first truthy value:
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder
The OR || operator exists since the beginning of JavaScript, so developers were using it for
such purposes for a long time.
On the other hand, the nullish coalescing operator ?? was added to JavaScript only recently,
and the reason for that was that people weren’t quite happy with ||.
The important difference between them is that:
●​ || returns the first truthy value.
●​ ?? returns the first defined value.
In other words, || doesn’t distinguish between false, 0, an empty string "" and
null/undefined. They are all the same – falsy values. If any of these is the first argument of
||, then we’ll get the second argument as the result.
In practice though, we may want to use the default value only when the variable is
null/undefined. That is when the value is really unknown/not set.
For example, consider this:
let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
●​ The height || 100 checks height for being a falsy value, and it really is.
●​ so the result is the second argument, 100.
●​ The height ?? 100 checks height for being null/undefined, and it’s not,
●​ so the result is height “as is”, that is 0.
If the zero height is a valid value, that shouldn’t be replaced with the default, then ?? does just
the right thing.

Precedence
The precedence of the ?? operator is rather low: 5 in the MDN table. So ?? is evaluated before =
and ?, but after most other operations, such as +, *.
So if we’d like to choose a value with ?? in an expression with other operators, consider adding
parentheses:
let height = null;
let width = null;
// important: use parentheses
let area = (height ?? 100) * (width ?? 50);
alert(area); // 5000
Otherwise, if we omit parentheses, then as * has the higher precedence than ??, it would
execute first, leading to incorrect results.
// without parentheses
let area = height ?? 100 * width ?? 50;
// ...works the same as this (probably not what we want):
let area = height ?? (100 * width) ?? 50;
Using ?? with && or ||
Due to safety reasons, JavaScript forbids using ?? together with && and || operators, unless
the precedence is explicitly specified with parentheses.
The code below triggers a syntax error:
let x = 1 && 2 ?? 3; // Syntax error
The limitation is surely debatable, but it was added to the language specification with the
purpose to avoid programming mistakes when people start to switch to ?? from ||.
Use explicit parentheses to work around it:
let x = (1 && 2) ?? 3; // Works
alert(x); // 2

Logical nullish assignment (??=)


The logical nullish assignment (x ??= y) operator only assigns if x is nullish (null or
undefined).
JavaScript Demo: Expressions - Logical nullish assignment

Syntax
expr1 ??= expr2

Short-circuit evaluation
The nullish coalescing operator is evaluated left to right, it is tested for possible short-circuit
evaluation using the following rule:
(some expression that is neither null nor undefined) ?? expr is short-circuit
evaluated to the left-hand side expression if the left-hand side proves to be neither null nor
undefined.
Short circuit means that the expr part above is not evaluated, hence any side effects of doing
so do not take effect (e.g., if expr is a function call, the calling never takes place).
Logical nullish assignment short-circuits as well meaning that x ??= y is equivalent to:
x ?? (x = y);
And not equivalent to the following which would always perform an assignment:
x = x ?? y;

Examples
Using logical nullish assignment
function config(options) {
[Link] ??= 100;
[Link] ??= 25;
return options;
}
config({ duration: 125 }); // { duration: 125, speed: 25 }
config({}); // { duration: 100, speed: 25 }

Summary
●​ The nullish coalescing operator ?? provides a short way to choose the first “defined”
value from a list.​
It’s used to assign default values to variables:
// set height=100, if height is null or undefined
●​ height = height ?? 100;
●​ The operator ?? has very low precedence, only a bit higher than ? and =, so consider
adding parentheses when using it in an expression.
●​ It’s forbidden to use it with || or && without explicit parentheses.

Operator precedence Table


The following table is ordered from highest (21) to lowest (1) precedence.
Pr Operator Asso Individual
ec type ciativ operators
e ity
d
e
n
ce

21 Grouping n/a ( … )

20 Member left-to … . …
Access -right

Computed left-to … [ … ]
Member -right
Access

new (with n/a new … ( …


argument )
list)
Function left-to … ( … )
Call -right

Optional left-to ?.
chaining -right

19 new right-t new …


(without o-left
argument
list)

18 Postfix n/a … ++
Increment

Postfix … --
Decrement

17 Logical right-t ! …
NOT (!) o-left

Bitwise ~ …
NOT (~)

Unary plus + …
(+)

Unary - …
negation
(-)

Prefix ++ …
Increment

Prefix -- …
Decrement

typeof typeof …

void void …

delete delete …

await await …

16 Exponenti right-t … ** …
ation (**) o-left
15 Multiplicati left-to … * …
on (*) -right

Division (/) … / …

Remainder … % …
(%)

14 Addition left-to … + …
(+) -right

Subtractio … - …
n (-)

13 Bitwise left-to … << …


Left Shift -right
(<<)

Bitwise … >> …
Right Shift
(>>)

Bitwise … >>> …
Unsigned
Right Shift
(>>>)

12 Less Than left-to … < …


(<) -right

Less Than … <= …


Or Equal
(<=)

Greater … > …
Than (>)

Greater … >= …
Than Or
Equal (>=)

in … in …

instance …
of instanceof

11 Equality left-to … == …
(==) -right

Inequality … != …
(!=)

Strict … === …
Equality
(===)

Strict … !== …
Inequality
(!==)

10 Bitwise left-to … & …


AND (&) -right

9 Bitwise left-to … ^ …
XOR (^) -right

8 Bitwise left-to … | …
OR (|) -right

7 Logical left-to … && …


AND (&&) -right

6 Logical left-to … || …
OR (||) -right

5 Nullish left-to … ?? …
coalescing -right
operator
(??)

4 Conditiona right-t … ? … :
l (ternary) o-left …
operator

3 Assignme right-t … = …
nt o-left

… += …

… -= …

… **= …
… *= …

… /= …

… %= …

… <<= …

… >>= …

… >>>= …

… &= …

… ^= …

… |= …

… &&= …

… ||= …

… ??= …

2 yield right-t yield …


o-left

yield* yield* …

1 Comma / left-to … , …
Sequence -right

You might also like