- Published on
JavaScript Quirks & Challenges: Part 1
- Authors
- Name
- Mason Tran
- @huykon
Overview
This series will let you know or remind you some weirds of Javascript programming language.
1. typeof null returns "object" instead of "null"
Yes, that's correct! It's one of the quirks in JavaScript. When you use the typeof
operator on null
, it returns object instead of null. This behavior has been present since the early days of JavaScript and is considered one of the language's historical oddities. It's important for developers to be aware of this behavior to avoid potential issues in their code.
For example:
console.log(typeof null) // Outputs: "object"
While this may seem counterintuitive, it's a well-known behavior and has been maintained for backward compatibility reasons. When checking for null
, it's generally recommended to use a direct comparison (===
) rather than relying on typeof. For example:
const myVar = null
if (myVar === null) {
console.log('myVar is null')
} else {
console.log('myVar is not null')
}
This way, you can perform an explicit check for null
without relying on the typeof
behavior.
2. NaN === NaN returns false
The equality operator (===
) returns false
when comparing two instances of NaN
. This behavior may seem counterintuitive at first, but it is by design.
The reason for this is that NaN
represents a value that is "Not a Number," and it is used to signify the result of an undefined or unrepresentable mathematical operation. Since the concept of "not a number" is inherently undefined, two instances of NaN
are considered not equal to each other.
Example:
console.log(NaN === NaN) // Outputs: false
To check if a value is NaN
, you should use the isNaN()
function:
console.log(isNaN(NaN)) // Outputs: true
This behavior ensures that when you encounter NaN
, you can reliably identify it using the isNaN()
function. If NaN === NaN
returned true, it might lead to unexpected behavior and make it more challenging to distinguish between a legitimate NaN
and other values in certain scenarios.
3. [] + [] returns an empty string
The +
operator is overloaded to perform both addition and concatenation. When you use the +
operator with two arrays, JavaScript will implicitly convert the arrays to strings and then concatenate those strings. If the arrays are empty, the result will be an empty string.
Here's an example:
console.log([] + []) // Outputs: ""
In this case, the empty arrays are converted to empty strings, and the concatenation results in an empty string.
It's important to note that the behavior of the +
operator depends on the types of the operands. When used with arrays, it performs string concatenation. However, if one of the operands is not an array, JavaScript will perform numeric addition instead of concatenation:
console.log([] + 5) // Outputs: "5" (array is converted to string, then concatenated with 5)
console.log([] + '5') // Outputs: "5" (array is converted to string, then concatenated with "5")
console.log([2] + [3]) // Outputs: "23" (arrays are converted to strings, then concatenated)
This behavior can be quirky, and it's essential for developers to be aware of how the +
operator behaves in different contexts.
4. typeof NaN returns "number"
The typeof
operator returns "number" when applied to NaN
. While NaN
stands for "Not a Number," its underlying representation in JavaScript is of the number data type. Therefore, typeof NaN
evaluates to "number".
For example:
console.log(typeof NaN) // Outputs: "number"
NaN
is considered a special value of the number type that represents the result of undefined or unrepresentable mathematical operations. The decision to classify NaN
as a number was made for practical reasons, even though it might not align with the intuitive understanding of the term "number" in everyday language.
5. 1 / 0 returns Infinity
The dividing a finite number by zero results in Infinity
.
Example:
console.log(1 / 0) // Outputs: Infinity
Similarly, dividing a negative finite number by zero results in -Infinity
:
console.log(-1 / 0) // Outputs: -Infinity
This behavior aligns with mathematical conventions, where division by zero is undefined in real numbers, but in the context of floating-point arithmetic in computing, JavaScript represents it as positive or negative infinity.
6. true + true returns 2
when you use the +
operator with two boolean values, JavaScript internally converts true
to 1
and false
to 0
before performing the addition. Therefore, true + true
evaluates to 2
.
For example:
console.log(true + true) // Outputs: 2
This behavior is a result of type coercion in JavaScript. When the +
operator is used with operands of different types (in this case, boolean values), JavaScript attempts to convert them to a common type before performing the operation. For addition, boolean values are converted to numeric values (1 for true
and 0 for false
), and then the addition is carried out.
It's important to be aware of these type coercion rules to avoid unexpected behavior in your code. If you want to concatenate boolean values as strings, you would need to convert them explicitly to strings:
console.log(String(true) + String(true)) // Outputs: "truetrue"
({} + [])
returns [object Object]
7. The expression {} + []
in JavaScript might behave unexpectedly due to the way the curly braces {}
are interpreted. In this context, JavaScript treats the curly braces as a block rather than an object literal.
When using the +
operator, JavaScript tries to convert the block {}
into a labeled statement. The expression essentially becomes an empty block followed by the unary plus operator acting on the array []
. The result is an empty block, and the array is then evaluated independently.
Here's how it works:
{} + [] // This is interpreted as an empty block + unary plus operator applied to an empty array
// The empty block is ignored, and the unary plus is applied to the empty array
+[] // This is equivalent to 0, as an empty array is coerced to 0
// Therefore, the overall result is 0
If you want to avoid this behavior and treat the curly braces as an object literal, you can wrap them in parentheses:
({} + []) // Outputs: "[object Object]"
In this case, the parentheses ensure that the curly braces are treated as an object literal, and the +
operator is applied to the concatenated string representation of the empty object and the empty array.
It's worth noting that expressions like these can be confusing and are often best avoided for clarity in code.
8. parseInt('07') returns 7
When you use parseInt()
to convert the string '07' to an integer, it treats the string as an octal (base-8) representation. In octal notation, '07' is equivalent to the decimal number 7.
console.log(parseInt('07')) // Outputs: 7
If you want to explicitly parse the string as a decimal number, you can specify the radix (base) as 10:
console.log(parseInt('07', 10)) // Outputs: 7
It's a good practice to include the radix parameter to avoid potential issues and make the code more explicit, especially when working with numbers that might have leading zeros.
9. 2 + 2 + '2' returns "42"
2 + 2 + '2'
// First addition: 2 + 2 = 4
// Second addition: 4 + '2' (string concatenation) => '42'
The addition operator is evaluated from left to right, so the first two 2's are added together to get 4
, and then that is concatenated with the string "2".
10. +!![]+!![]+!![] returns 3
console.log(+!![] + !![] + !![]) // Outputs: 3
Let's break down the expression +!![] + !![] + !![]
:
!![]
: This is a double NOT operator applied to an empty array ([]
). The double NOT operator converts any truthy or falsy value to its corresponding boolean representation. An empty array is a truthy value, so !![] evaluates to true.+!![]
: Here, the unary plus (+
) operator is used to convert the boolean value true to its numeric equivalent, which is 1.+!![] + !![]
: The first part,+!![]
, results in1
, and then you add anothertrue
, so the expression evaluates to1 + 1
, which is2
.+!![] + !![] + !![]
: Adding another true with+!![]
gives2 + 1
, which equals3
.
So, indeed, +!![] + !![] + !![]
evaluates to 3
. The key points here are the use of the double NOT operator (!!
) to convert the empty array to true
and the use of the unary plus operator to convert boolean values to their numeric equivalents.