Skip to content

JavaScript 类型转换深度解析

强制类型转换

parseInt 和 parseFloat

  • parseInt 从左向右提取有效数字
  • parseFloat 解析浮点数
  • 第二个参数指定进制(2-36)
javascript
parseInt("10"); // 10
parseInt("10px"); // 10
parseInt("n10px"); // NaN

parseInt(27.2, 0); // 27 (基数为0时当作10进制处理)
parseInt(0, 1); // NaN (基数必须在2-36之间)
parseInt("0013", 2); // 1 (二进制001 -> 1)
parseInt("14px", 3); // 1 (三进制1 -> 1)
parseInt(123, 4); // 27 (4进制: 1*16 + 2*4 + 3*1 = 27)

一元加号运算符

  • 将值转换为数字类型
  • BigIntSymbol 会报错
javascript
console.log(+null); // 0
console.log(+undefined); // NaN
console.log(+"123aa"); // NaN
console.log(+{}); // NaN
console.log(+true); // 1

// BigInt 和 Symbol 不能使用一元加号
console.log(+10n); // TypeError
console.log(+Symbol("a")); // TypeError

布尔值转换规则

if 语句中的假值

以下值在布尔上下文中会被转换为 false

  • undefined
  • null
  • NaN
  • 0
  • '' (空字符串)
javascript
const result = {};
const obj = { name: 0 };

// 错误方式:0 会被转换为 false
if (obj.name) {
  result.name = obj.name;
}

// 正确方式:使用 hasOwnProperty 检查属性存在性
if (obj.hasOwnProperty("name")) {
  result.name = obj.name;
}

逻辑非运算符

  • ! 将值转换为布尔类型并取反
  • 假值取反为 true,真值取反为 false
javascript
console.log(!0); // true
console.log(!""); // true
console.log(!null); // true
console.log(!undefined); // true
console.log(!NaN); // true
console.log(!{}); // false
console.log(![]); // false

相等比较(==)的隐式转换

特殊规则

  1. nullundefined 相等
  2. NaN 不等于任何值(包括自身)
  3. 布尔值会先转换为数字
  4. 字符串和数字比较,字符串转为数字
  5. 对象与原始值比较,对象转为原始值
  6. 对象与对象比较引用地址
javascript
console.log(null == undefined); // true
console.log(null == 0); // false
console.log("0" == false); // true (false→0, '0'→0)
console.log([] == ![]); // true (![]→false→0, []→''→0)
console.log("000" == 0); // true
console.log([true] == 1); // false ([true]→'true'→NaN)

加法运算符(+)的转换规则

二元加法规则

  1. 如果有操作数是对象,先转为原始值
  2. 如果有一个操作数是字符串,执行字符串拼接
  3. 否则,将两个操作数转为数字进行加法运算
javascript
console.log([] + []); // '' (数组转字符串)
console.log([] + {}); // '[object Object]'
console.log({} + []); // '[object Object]' (Node.js) | 0 (浏览器控制台)
console.log({} + {}); // '[object Object][object Object]'

对象到原始值的转换机制

转换过程

  1. 检查是否存在 Symbol.toPrimitive 方法
  2. 没有则根据提示(hint)调用:
    • "number": 先 valueOf()toString()
    • "string": 先 toString()valueOf()
    • "default": 同 "number"
javascript
const obj = {
  [Symbol.toPrimitive](hint) {
    console.log(`Hint: ${hint}`);
    if (hint === "number") return 10;
    if (hint === "string") return "hello";
    return true;
  },
};

console.log(+obj); // Hint: number → 10
console.log(`${obj}`); // Hint: string → 'hello'
console.log(obj + 5); // Hint: default → true + 5 = 6

默认 valueOf 和 toString

javascript
// Array
[1, 2]
  .valueOf() // [1, 2] (数组本身)
  [(1, 2)].toString()(
    // "1,2"

    // Object
    {}
  )
  .valueOf()(
    // {} (对象本身)
    {}
  )
  .toString(); // "[object Object]"

// Date
const now = new Date();
now.valueOf(); // 时间戳 (数字)
now.toString(); // 可读日期字符串

对象比较的特殊性

  • 对象比较的是引用地址,不会进行隐式类型转换
  • 不会调用 Symbol.toPrimitivevalueOftoString
javascript
const obj1 = { value: 10 };
const obj2 = { value: 10 };

console.log(obj1 == obj2); // false (不同引用)
console.log(obj1 === obj2); // false
console.log(obj1 != obj2); // true

复杂隐式转换案例分析

案例 1:数组和对象的组合

javascript
const arr = [4, 10];
arr[Symbol.toPrimitive] = function (hint) {
  return hint;
};
arr.valueOf = function () {
  return this;
};

const obj = {};

// 转换步骤:
// 1. +arr → "number" (字符串)
// 2. "number" + obj → "number[object Object]"
// 3. "number[object Object]" + arr → "number[object Object]default"
// 4. "number[object Object]default" + obj → "number[object Object]default[object Object]"

console.log(+arr + obj + arr + obj);
// 输出: "number[object Object]default[object Object]"

案例 2:数组和布尔值的转换

javascript
// 解析: [] == ![]
// 1. ![] → false (布尔值)
// 2. false → 0 (数字)
// 3. [] → "" → 0 (数字)
// 4. 0 == 0 → true

const val = [] == ![]; // true

// 解析: [1, 1] == [1, "1"]
// 数组比较引用地址,不是内容
console.log([+val, [] + 1] == [1, "1"]); // false

案例 3:对象和空数组的转换

javascript
// 步骤解析:
// 1. +{} → NaN
// 2. +[] → 0
// 3. (NaN + []) → "NaN" (字符串拼接)
// 4. "NaN"[0] → "N"

const val = (+{} + [])[+[]];
console.log(val); // "N"

类型转换总结表

转换类型规则说明
数字转换null→0, undefined→NaN, 字符串解析数字,true→1, false→0
布尔转换假值(null,undefined,0,NaN,'')→false, 其他 →true
字符串转换数组 → 元素逗号分隔,对象 →[object Object]null→"null", undefined→"undefined"
对象转换优先使用Symbol.toPrimitive,然后根据 hint 调用valueOf/toString