JavaScript 隐式类型转换的 6 大核心场景
一、使用 ==
宽松相等比较时
// 经典面试题[] == ![] // true// 转换路径:// 1. ![] → false(空数组转布尔为true,取反后为false)// 2. [] == false → [] == 0// 3. [].valueOf() → [](非原始值),调用 toString() → ""// 4. "" == 0 → 0 == 0 → true// 5. true == '1' → true == 1 → true
转换优先级表
比较双方类型 | 转换规则 |
---|---|
Number vs String | String → Number |
Boolean vs 其他类型 | Boolean → Number |
Object vs 原始类型 | Object → 原始值(优先 valueOf → toString) |
null vs undefined | 直接相等 |
二、算术运算符操作时
1. 加法运算符 +
"5" + 2 = "52" // 字符串优先拼接"5" - 2 = 3 // 转换为数字运算[] + {} = "[object Object]" // [] → "", {} → "[object Object]"
2. 其他运算符 -
*
/
%
"10" - "2" = 8 // 转为数字运算"10a" * 2 = NaN // 转换失败返回 NaN
三、逻辑判断中的真值转换
if (0) { /* 不执行 */ } // 0 → falsewhile ("") { /* 不执行 */ } // "" → falseconst val = null;console.log(val || "default"); // null → false,输出 "default"
Falsy 值列表
值 | 转换结果 |
---|---|
0, -0 | false |
"" | false |
null | false |
undefined | false |
NaN | false |
四、模板字符串嵌入变量时
const obj = { toString: () => "OBJ" };console.log(`Value: ${obj}`); // "Value: OBJ"(自动调用 toString)
五、对象参与原始值操作时
const date = new Date();// 优先调用 toString()console.log("Today is " + date); // "Today is Wed Oct 18 2023..."
// 优先调用 valueOf()console.log(date * 1); // 输出时间戳(数值运算)
对象转换优先级
- 检查
Symbol.toPrimitive
方法 - 数值上下文优先调用
valueOf()
- 字符串上下文优先调用
toString()
六、数组的特殊转换行为
// 数组转字符串[1, 2] + [3, 4] = "1,23,4" // 数组 → "1,2" + "3,4"
// 空数组转换[] == 0 // true([] → "" → 0)Number([]) // 0Boolean([]) // true(所有对象转布尔都是true)
防御式编程建议
- 严格模式:始终使用
===
代替==
- 显式转换:用
Number()
,String()
,Boolean()
明确意图 - 类型守卫:对函数参数进行类型校验
function sum(a, b) {if (typeof a !== "number" || typeof b !== "number") {throw new Error("参数必须为数字");}return a + b;}