Here's a cool talk about everything I've written notes on below.
Here's a cool table that demonstrates type comparison for ==
and ===
. It also shows if
statement type-coercion.
Here's what Mozilla have to say about comparison operators (relational & equality as described below)
Type Coercion¶
JavaScript is dynamically typed and uses type coercion for comparison of variables. This affects how boolean statements are evaluated, and how equality operators work.
Truthy Falsy Values¶
JavaScript implicitly converts values to booleans when used in statements that expect booleans (if
, for
, while
, do-while
)
Note: switch
statements don't expect booleans necessarily so no type coercion is applied.
function printIsTruthy(value) {
printStatement = (value) ? `${value} is truthy` : `${value} is falsy`
console.log(printStatement)
}
Numeric values:¶
printIsTruthy(123)
printIsTruthy(0)
printIsTruthy(-1)
printIsTruthy(NaN)
String values¶
printIsTruthy('abc')
printIsTruthy('')
Null and Undefined¶
printIsTruthy(null)
printIsTruthy(undefined)
Collections¶
printIsTruthy({}) // object
printIsTruthy([]) // array
Logical Operators¶
Logical operators &&
||
will implicitly convert operands to booleans (depending on the context) but the operand value itself is returned - not the converted boolean value.
var value = 0 || 'abc'
console.log(value)
This trick is sometimes used for setting default values - the or
operator is looking from left-to-right for the first true
operand to return.
0 is falsy so is not returned, the non-empty string is truthy and so is returned and used to set the variable.
Mathematical Operators + String Concatenation¶
When creating calculations using +
-
/
*
%
values are implicitly converted to numbers. (Except dates - which are converted to Strings...?!)
var value = true + null + 3
console.log(value)
In this example true
has been converted to 1, null
has been converted to 0, and 3 is obviously 3
Since +
is used for both addition of numbers and concatenation of strings (i.e. it is overloaded) there's extra quirks to be aware of.
var value = '3' + 0
console.log(value)
Since the code is evaluated and executed from left to right - the statement will first be treated as a mathematical statement - it will convert any non-string values to integers and apply mathematical operations - but as soon as it hits a string the values will start to be converted to strings and the +
operator becomes a string concatenation.
var value = 0 + 1 + '3' + false
console.log(value)
var value = true + 1 + 2 + '3' + 4 + 5 + true
console.log(value)
Comparison Operators¶
Relational Operators¶
When performing comparisons >
<
>=
<=
all values are implicitly converted to numbers (including dates)
Exception: strings are compared using lexicographical string comparison (alphabetical order)
Note: Any comparison involving NaN
will evaluate to false
var value = false < '123'
console.log(value)
false
has been converted to 0 to be used in the <
comparison, and the string has been converted to a number.
false + true > '0' + 2
In this case the string concatenation seems to convert values to numerics before performing the comparison
'0' + 2 < false + true
Equality Operators¶
In JavaScript, values are considered equal if they are:
- identical boolean values
- identical strings
- ... any primitives of the same value
- numerically equivalent (as in +0 == -0)
- a reference to the same object / array / reference value
NaN
is not equal to anything - including itself
Two distinct objects are never equal for either strict or abstract comparisons
==
applies type-coercion first if the types are different, then checks for equality. It uses something called the "abstract equality comparison algorothm", a series of 22 steps to determine equality.
We know that null
is converted to 0 when used with mathematical or comparison operators. So you would think it would be converted to 0 in the ==
equality check.
var value = (null == 0)
console.log(value)
null
is only coerced as undefined
when using the ==
operator
There are other strange outputs from using the ==
operator - they can be explained by looking at the abstract equality comparison algorithm" but in short it doesn't always return what's expected.
When using JavaScript it's safest to always use the ===
operator unless you have a specific reason for using ==
===
doesn't apply type-coercion and uses the "strict equality algorithm".
Testing out some stuff¶
Object equality¶
It was mentioned above but just to demonstrate to myself:
Checking if two objects are equal using ==
and ===
var obj1 = {'value':'blah'}
var obj2 = {'value':'blah'}
obj1==obj2
obj1===obj2
They're not because they reference different objects in memory.
Checking if two arrays are equal using ==
and ===
var arr1 = [1,2,3]
var arr2 = [1,2,3]
arr1==arr2
arr1===arr2
They're not - again because of references.
Null == Undefined¶
The Mozilla page on comprison operations says:
Null and Undefined Types are strictly equal to themselves and abstractly equal to each other.
null==undefined
null===undefined
So ==
can be useful in the case where we don't care whether something is null
or undefined
, we just want to check whether it has a defined value or not.
var value = null
if (value==undefined) {
console.log('No value')
}