Introduction#
Due to numerous historical reasons, JavaScript does not have strong control over types (which led to the birth of TypeScript). In daily development and when dealing with coding problems, developers are often tormented by JavaScript's "implicit conversions". Even experienced JavaScript developers sometimes make mistakes. This article covers all cases of implicit conversions in JavaScript, allowing you to master JavaScript's implicit conversions in one go.
A diagram showing the hellish implicit conversions in JavaScript:
1. Subtraction, Multiplication, Division#
⭐️When applying mathematical operators (-
, *
, /
) to non-Number
types, they will be converted to Number
types first.
1 - true // 0, true is converted to the number 1, then 1 - 1 is executed
1 - null // 1, null is converted to the number 0, then 1 - 0 is executed
1 * undefined // NaN, undefined is converted to NaN
2 * ['5'] // 10, ['5'] is first converted to '5', then '5' is converted to the number 5
The conversion of ['5'] mentioned above involves unboxing, which will be explained in another article in the future.
2. Special Case of Addition#
⭐️Why is addition treated differently? Because in JavaScript, +
can also be used for string concatenation. Remember the following 3 rules:
- When one side is of type
String
, it is recognized as string concatenation and the other side will be converted to aString
type first. - When one side is of type
Number
and the other side is a primitive type, the primitive type will be converted to aNumber
type. - When one side is of type
Number
and the other side is a reference type, both the reference type and theNumber
type will be converted to strings before concatenation.
⭐️The above 3 rules have priorities from high to low, meaning that 3+'abc'
will follow rule 1, while 3+true
will follow rule 2.
123 + '123' // 123123 (rule 1)
123 + null // 123 (rule 2)
123 + true // 124 (rule 2)
123 + {} // 123[object Object] (rule 3)
Type Conversions in Logical Statements#
When using if
, while
, and for
statements, we expect the expression to be a Boolean
, so implicit type conversions always accompany these statements. There are two situations:
1. Single Variable#
⭐️If there is only a single variable, it will be converted to a Boolean value first.
You can refer to the conversion table in the Appendix to determine the Boolean value of various types after conversion.
However, there is a trick here:
Only null
, undefined
, ''
, NaN
, 0
, and false
are false
, while all other cases are true
, such as {}
, []
.
2. Comparison using ==#
Although we can use ===
strictly, it is still necessary to understand the behavior of ==
.
⭐️Based on the data types on both sides of ==
, we have summarized 5 rules:
- Rule 1: Comparisons involving
NaN
always returnfalse
(including comparing with itself).
NaN == NaN // false
- Rule 2: When comparing a Boolean with any other type, the Boolean is first converted to a Number.
true == 1 // true
true == '2' // false, true is converted to 1, not '2' converted to true
true == ['1'] // true, true is converted to 1, ['1'] is unboxed to '1', then refer to rule 3
true == ['2'] // false, same as above
undefined == false // false, false is first converted to 0, then refer to rule 4
null == false // false, same as above
- Rule 3: When comparing a
String
with aNumber
, theString
is first converted to aNumber
.
123 == '123' // true, '123' is first converted to 123
'' == 0 // true, '' is first converted to 0
Rule 4: The comparison result of null == undefined
is true
, and other comparisons involving null
, undefined
, and any other value are false
.
null == undefined // true
null == '' // false
null == 0 // false
null == false // false
undefined == '' // false
undefined == 0 // false
undefined == false // false
Rule 5: When comparing a primitive type
with a reference type
, the reference type is converted to a primitive type according to the ToPrimitive
rule.
⭐️The
ToPrimitive
rule is the rule for converting a reference type to a primitive type. It follows the pattern ofvalueOf
first and thentoString
to obtain a primitive type.
If a primitive type cannot be obtained, a TypeError
will be thrown.
'[object Object]' == {}
// true, when comparing an object with a string, the object is converted to a primitive value through toString
'1,2,3' == [1, 2, 3]
// true, same as above, [1, 2, 3] is converted to a primitive value through toString
Let's practice with a few special questions!
1. [] == ![]
- Step 1: ![] becomes false
- Step 2: Apply rule 2, the question becomes: [] == 0
- Step 3: Apply rule 5, the valueOf of [] is 0, so the question becomes: 0 == 0
- Therefore, the answer is true!
2. [undefined] == false
- Step 1: Apply rule 5, [undefined] becomes '', so the question becomes: '' == false
- Step 2: Apply rule 2, the question becomes: '' == 0
- Step 3: Apply rule 3, the question becomes: 0 == 0
- Therefore, the answer is true!
// But if([undefined]) is true!
3. More questions
Discover more strange questions in your daily life. (Sad life)
⭐️I strongly recommend that you find all kinds of strange questions and practice the 5 rules mentioned above repeatedly until you are familiar with them.
Appendix 1: Conversion Table#
This table is quite useful. You can refer to it when applying the conversion rules mentioned above.