JavaScript 类型转换机制

隐式转换和显式转换的规则与常见场景

问题

JavaScript 中的类型转换机制是什么?隐式转换和显式转换有哪些规则?

解答

显式转换

手动调用转换函数进行类型转换。

// 转换为字符串
String(123)          // "123"
String(true)         // "true"
String(null)         // "null"
String(undefined)    // "undefined"
String([1, 2])       // "1,2"
String({})           // "[object Object]"

// 转换为数字
Number("123")        // 123
Number("123abc")     // NaN
Number("")           // 0
Number(true)         // 1
Number(false)        // 0
Number(null)         // 0
Number(undefined)    // NaN
Number([])           // 0
Number([1])          // 1
Number([1, 2])       // NaN

// 转换为布尔值
// 假值:false, 0, -0, "", null, undefined, NaN
Boolean(0)           // false
Boolean("")          // false
Boolean(null)        // false
Boolean(undefined)   // false
Boolean(NaN)         // false
// 其他都是 true
Boolean([])          // true(空数组是真值)
Boolean({})          // true(空对象是真值)

隐式转换

JavaScript 在运算时自动进行的类型转换。

1. 字符串拼接(+ 运算符)

// 有字符串参与时,+ 做字符串拼接
1 + "2"              // "12"
"1" + 2              // "12"
1 + 2 + "3"          // "33"(先算 1+2=3,再拼接)
"1" + 2 + 3          // "123"(从左到右依次拼接)

// 对象转字符串
1 + {}               // "1[object Object]"
1 + []               // "1"(空数组转为空字符串)
1 + [1, 2]           // "11,2"

2. 数学运算(-、*、/、%)

// 非 + 运算符会将操作数转为数字
"6" - 1              // 5
"6" * "2"            // 12
"6" / "2"            // 3
"abc" - 1            // NaN

// 一元 + 运算符
+"123"               // 123
+true                // 1
+[]                  // 0
+{}                  // NaN

3. 比较运算

// == 会进行类型转换,=== 不会
1 == "1"             // true
1 === "1"            // false

// null 和 undefined
null == undefined    // true
null === undefined   // false
null == 0            // false(特殊规则)

// 对象与原始值比较,对象会调用 valueOf/toString
[1] == 1             // true([1] -> "1" -> 1)
["1"] == 1           // true

4. 逻辑运算

// 转为布尔值判断,但返回原值
"hello" && "world"   // "world"
"" && "world"        // ""
"hello" || "world"   // "hello"
"" || "world"        // "world"

// 常用于默认值
const name = input || "default"

// !! 转布尔值
!!1                  // true
!!0                  // false
!!""                 // false
!!"hello"            // true

对象转原始值

对象转原始值时,会调用内部方法 ToPrimitive

const obj = {
  valueOf() {
    console.log("valueOf")
    return 100
  },
  toString() {
    console.log("toString")
    return "obj"
  }
}

// 数字运算优先调用 valueOf
obj + 1              // valueOf -> 101
obj * 2              // valueOf -> 200

// 字符串场景优先调用 toString
String(obj)          // toString -> "obj"
`${obj}`             // toString -> "obj"

// 特殊:Date 对象优先调用 toString
const date = new Date()
date + 1             // "Mon Nov 24 2025 ...1"

常见面试陷阱

// [] 和 {} 的转换
[] + []              // ""(两个空字符串拼接)
[] + {}              // "[object Object]"
{} + []              // 0({} 被解析为代码块,+[] 转为 0)
({}) + []            // "[object Object]"

// 比较运算
[] == false          // true([] -> "" -> 0, false -> 0)
![] == false         // true(![] -> false)
[] == ![]            // true([] -> 0, ![] -> false -> 0)

// NaN
NaN == NaN           // false
Number.isNaN(NaN)    // true

关键点

  • 显式转换用 String()Number()Boolean() 函数
  • + 有字符串时做拼接,-*/ 转数字运算
  • 假值只有 6 个:false0""nullundefinedNaN
  • 对象转原始值调用 valueOftoString,顺序取决于场景
  • === 避免隐式转换带来的问题