所属板块:1. 数据类型与内存机制
记录日期:2026-03-xx
更新:根据遇到的新奇葩题补充
1. 为什么会有隐式类型转换?
JavaScript 在某些操作符(==、+、if 判断等)下,会自动把操作数转换成其他类型。
这是语言设计导致的“便利”,但也制造了很多坑。
记住:生产代码里能用 === 就用 ===,尽量避免隐式转换带来的意外。
2. 常见触发隐式转换的场景
- 比较运算符 ==(不严格相等,会转换)
- 加号 +(字符串拼接优先,其余转数字相加)
- if / 三元 / 逻辑运算(转为布尔值)
- 数学运算(- * / %)(两边都转成数字)
- 对象参与运算时(会调用 ToPrimitive)
3. 转布尔值的规则(if 判断、!!、三元等)
只有以下 6 个值转为 false,其余全为 true:
- false
- 0
- -0
- ""(空字符串)
- null
- undefined
- NaN
常见反直觉例子:
if ([]) { console.log("[] 为 true") } // 通过
if ({}) { console.log("{} 为 true") } // 通过
if ("0") { console.log("\"0\" 为 true") } // 通过
if (new Date()) { console.log("Date 对象为 true") } // 通过
4. == 的转换规则(最容易出问题的)
== 的转换优先级大致是:
- 如果两边都是 null 或 undefined → true
- 如果一边是 null/undefined,另一边不是 → false
- 如果两边都是原始类型 → 都转成数字比较(字符串转数字,布尔转 0/1)
- 如果有一边是对象 → 对象调用 ToPrimitive(优先 valueOf → toString)
- 如果两边都是对象 → 比较是否同一引用
经典例子汇总:
console.log(0 == "0"); // true (字符串 "0" 转数字 0)
console.log(0 == false); // true (false 转 0)
console.log("" == false); // true ("" 转 0,false 转 0)
console.log([] == ![]); // true ← 经典题
// [] == ![] 拆解:
![] → false (数组转布尔为 true,取反为 false)
[] == false → [] 转成 ""(空字符串) → "" == false → "" 转 0,false 转 0 → 0 == 0 → true
另一个变态组合:
console.log([] == 0); // true ([] → "" → 0)
console.log([] == ""); // true ([] → "")
console.log([[]] == ""); // false ([[]] → "0" → 不等于 "")
console.log({} == "[object Object]"); // false ({} → "[object Object]" 但不等于字符串本身)
5. + 号的特殊行为
- 是唯一一个既能做数学加法又能做字符串拼接的运算符,规则:
- 只要有一边是字符串 → 都转成字符串拼接
- 两边都不是字符串 → 都转成数字相加
console.log(1 + "2"); // "12"
console.log(1 + +"2"); // 3 (+"2" 强制转数字)
console.log([] + {}); // "[object Object]" ([] → "",{} → "[object Object]")
console.log({} + []); // 0 ({} 被当成代码块,+[] → 0)
console.log(1 + {}); // "1[object Object]"
6. 对象转原始类型(ToPrimitive)过程
当对象参与 ==、+ 等操作时,会按以下顺序尝试转换:
- 如果有 [Symbol.toPrimitive] 方法 → 调用它
- 否则调用 valueOf()
- 否则调用 toString()
- 如果还不行 → TypeError
示例:
const obj = {
valueOf() { return 42; },
toString() { return "hello"; }
};
console.log(obj + 1); // 43 (优先 valueOf)
console.log("" + obj); // "hello"(+ 字符串时优先 toString? 其实还是 valueOf 先)
// 更准确:+ 号两边原始类型不同时,先 ToPrimitive 再决定
7. 小结 & 实际使用建议
- 永远优先用 ===,除非你明确知道要利用转换(极少情况)
- 面试/刷题时,记住 [] == ![]、{} + []、[] + {} 这三组经典组合的答案
- 日常写代码遇到不确定类型时,先用 getType()(上一篇文章封装的)打印出来,再决定怎么处理
下一篇文章会记录内存机制、垃圾回收和常见内存泄漏场景。
返回总目录:戳这里