一文搞懂 JavaScript 隐式类型转换

109 阅读4分钟

1 类型转换

1.1. 转换表

原始类型string, number, bigint, boolean, null, undefined, symbol

✅ 引用类型:Object、Array、Function、Date、RegExp、Map/Set 等。

✅ 包装类型:String、Number、Boolean 等原始类型的临时对象形式。

以下是各类型之间的 转换规则

转换为Number时特殊点

  • 非数字字符串、undefined、NaN 为 NaN

  • -0为-0,-1为 -1

  • 空字符串为 0

1.2. 隐形转换

1.2.1. 加 +

规则 (优先级从高到低)

  1. 当一侧为String时,优先将另一侧转换为字符串类型
  2. 当一侧为Number时,另一侧为原始类型,则将原始类型转换为Number类型
  3. 当一侧为Number时,另一侧为引用类型,则将引用类型和Number类型转换为字符串再拼接
'add' + {a:1} // add + [object object] -> add[object object] (规则1123 + true // 123 + 1 -> 124 (规则2123 + {a:1} // 123 + [object object] -> 123[object object] (规则3123 + undefined // 123 + NaN -> NaN (规则2
1.2.2.2. 减乘除(- * /)

规则:

先将非Number类型转换为Number类型

1 - true // 1 - 1 -> 0
null - true // 0 - 1 -> -1
1 * undefined // 1 * NaN -> NaN
2 * ["5"]  // 2 * '5' -> 2 * 5 ->10
2 / {a:1} // 2 / '[object Object]' -> NaN
1.2.3. 逻辑语句中的转换

如果只有单个变量,会将变量转换为Boolean值,参考原始值转换表

  • null、undefined、""、NaN 、0、-0、 false 都是 false
1.2.4. 使用 == 比较转换规则

规则:

  1. NaN和其他类型比较永远返回false 包括自己
  2. Boolean和其他任何类型比较,Boolean首先被转换为Number
true == 1 // 1 == 1 -> true
false == 0 // 0 == 0 -> true

3. String 和 Number 比较,先将String转换为Number类型

'123' == 123 // 123 == 123 true
'abc' == 123 // NaN == 123 false
undefined == 123 // NaN == 123 false

4. null == undefined 比较结果都是 true,null 、undefined和任何类型比较都是false 5. 原生类型和引用类型做比较时,引用类型会依照 ToPrimitive 规则转换为原始类型

ToPrimitive规则:是引用类型转换为原始类型的转变规则,遵循先valueOf 后 toString的模式得到一个原始类型

如果没有得到一个原始类型,就会抛出 TypeError

'[object Object]' == {} // true

6. !(逻辑非)的优先级 高于 ==(宽松相等)

[] == ![][] == ( ![] )  // 先计算 ![]
📌 核心规则:
  1. ==:优先转数字(除 null/undefined 特殊),涉及 !! 或 + 的转换。
  2. +:若有一方是字符串,则拼接;否则尝试转数字。
  3. -、*、/:强制转数字,失败则 NaN。

📝 JavaScript 隐式类型转换模拟考试(分类题型)

题目

一、宽松相等( ==

基础题
  1. "5" == 5
  1. true == 1
  1. null == undefined
  1. "" == 0
  1. [] == false
进阶题
  1. [1, 2] == "1,2"
  1. {} == {}
  1. "0" == false
  1. "\n" == 0
  1. [null] == ""
反直觉案例
  1. [] == ![]
  1. "0" == []
  1. "true" == true
  1. NaN == NaN
  1. document.all == undefined (浏览器环境)

二、 + ****运算符

基础题
  1. 1 + "1"
  1. "2" + 2
  1. true + false
  1. [] + []
  1. [] + {}
进阶题
  1. {} + []
  1. [1, 2] + [3, 4]
  1. "1" + +"2"
  1. +"1" + +"2"
  1. 1 + null + "3"
反直觉案例
  1. {}.toString() + []
  1. [,,,] + [,,]
  1. function aa(){} + []
  1. 0 + {} + []
  1. "".concat([1, 2]) + [3, 4]

三、 - * / ****运算符

基础题
  1. "5" - "2"
  1. "2" * "3"
  1. "10" / "2"
  1. true - false
  1. null - 1
进阶题
  1. [] - {}
  1. "5" - null
  1. "a" * "b"
  1. undefined / 1
  1. [2] * [3]
反直觉案例
  1. "-1" - "-1"
  1. true * "10"
  1. "" - 1
  1. {} - []
  1. +[] - +{}

🔍 答案及解析


📌 一、宽松相等( == )答案

题目答案解析
1. "5" == 5true数字与字符串比较,字符串转数字 5
2. true == 1truetrue转数字 1
3. null == undefinedtrue特殊规则
4. "" == 0true空字符串转数字 0
5. [] == falsetrue[]""0false0
进阶题
6. [1,2] == "1,2"true数组 toString()后比较
7. {} == {}false两个不同对象的引用
8. "0" == falsetruefalse0"0"0
9. "\n" == 0true空白字符转数字 0
10. [null] == ""true[null]""
反直觉案例
11. [] == ![]true![]false0[]""0
12. "0" == []false[]"""0"""
13. "true" == truefalse"true"NaNtrue1
14. NaN == NaNfalseNaN不等于任何值,包括自身
15. document.all == undefinedtrue历史遗留问题typeof document.all 等于 undefined

📌 二、 + ****运算符答案

题目答案解析
基础题
1. 1 + "1""11"数值转字符串拼接
2. "2" + 2"22"同上
3. true + false1true1false0
4. [] + []""数组转空字符串
5. [] + {}"[object Object]"{}转为 [object Object]
进阶题
6. {} + []0{}被解析为空代码块,+[]0
7. [1,2] + [3,4]"1,23,4"数组 toString()拼接
8. "1" + +"2""12"+"2"2,再拼接
9. +"1" + +"2"3两次一元加号转数字相加
10. 1 + null + "3""13"1 + null1 + 0,然后拼接 "3"
反直觉案例
11. {}.toString() + []"[object Object]"字符串拼接
12. [,,,] + [,,]",,,"稀疏数组的 toString()[,,,].toString() 等于 ",,"[,,].toString() 等于 ","比如 [1,2,] -> 1, 2 而不是 1,2,
13. function(){} + []0函数声明被忽略,+[]0
14. 0 + {} + []"0[object Object]"从左到右运算
15. "".concat([1,2]) + [3,4]"1,23,4"concat不改变原数组,toString()处理

📌 三、 - * / ****运算符答案

题目答案解析
基础题
1. "5" - "2"3字符串转数字计算
2. "2" * "3"6同上
3. "10" / "2"5同上
4. true - false1true1false0
5. null - 1-1null0
进阶题
6. [] - {}NaN[]0{}NaN
7. "5" - null5null0
8. "a" * "b"NaN无法转数字
9. undefined / 1NaNundefinedNaN
10. [2] * [3]6[2]2[3]3
反直觉案例
11. "-1" - "-1"0转为数字计算
12. true * "10"10true1"10"10
13. "" - 1-1""0
14. {} - []NaN{}无法转数字
15. +[] - +{}NaN+[]0+{}NaN