JS类型转换全攻略:==、===、隐式与显式转换一篇全懂!

479 阅读4分钟

你是否遇到过这样的疑惑:

  • 为什么1 == '1'是true,而1 === '1'却是false?
  • if语句、加号运算时,变量的类型怎么就悄悄变了?
  • obj + ''+objBoolean(obj)背后到底发生了什么?
    类型转换是JS开发中最容易被忽视、却又最容易踩坑的知识点。今天就带你用最通俗的方式,彻底搞懂JS里的各种类型转换!

一、== 和 === 的区别

基本用法

console.log(1 == '1'); // true
console.log(1 === '1'); // false
  • == 会发生隐式类型转换,只判断值是否相等。
  • === 不发生类型转换,值和类型都要相等才为true。

二、类型转换的两大方式

1. 显式类型转换

  • 转布尔Boolean(x)
  • 转数字Number(x)
  • 转字符串String(x)

示例:

console.log(Boolean(0)); // false
console.log(Number('123')); // 123
console.log(String(456)); // '456'

2. 隐式类型转换

  • 代码运行时自动发生,不需要你手动调用。
  • 常见场景:四则运算、判断语句、==比较等。

示例:

console.log(1 + '2'); // '12',数字和字符串相加,数字被转成字符串
console.log('5' - 2); // 3,字符串被转成数字
if ('0') { console.log('会执行'); } // 字符串'0'被转成true

三、原始类型与引用类型的转换

1. 原始类型转原始类型

  • 直接用Boolean(x)Number(x)String(x)即可。

2. 引用类型转原始类型

  • 转布尔:任何对象转布尔都是true
  • 转字符串:String(obj)会调用ToPrimitive(obj, String)
  • 转数字:Number(obj)会调用ToPrimitive(obj, Number)

四、ToPrimitive原理揭秘

JS在把对象转成原始类型时,会走一套“优先级”流程:

1. ToPrimitive(obj, String)

  • 先看是不是原始类型,是就直接返回
  • 否则先调用toString(),如果返回原始类型就用它
  • 否则再调用valueOf(),如果返回原始类型就用它
  • 都不是就报错

2. ToPrimitive(obj, Number)

  • 先看是不是原始类型,是就直接返回
  • 否则先调用valueOf(),如果返回原始类型就用它
  • 否则再调用toString(),如果返回原始类型就用它
  • 都不是就报错

示例:

let obj = {
  valueOf() { return 42; },
  toString() { return 'hello'; }
};
console.log(Number(obj)); // 42
console.log(String(obj)); // 'hello'

五、valueOf 和 toString 的作用

  • valueOf():对象转原始类型时优先调用(数字场景)
  • toString():对象转字符串时优先调用(字符串场景)

示例:

let arr = [1,2,3];
console.log(arr.toString()); // '1,2,3'
console.log({}.toString()); // '[object Object]'

六、隐式类型转换的常见场景

  1. 四则运算:+ - * / %

    • +:只要有字符串,优先拼接
    • 其他运算符会把字符串转成数字
  2. 判断语句:if、while、==、!=、<、>、<=、>=

    • 会自动把变量转成布尔值或数字

示例:

console.log(1 + '2'); // '12'
console.log('5' - 2); // 3
if ('') { console.log('不会执行'); }

七、+ 运算符的特殊规则

  • 作为一元运算符:+x会把x转成数字
  • 作为二元运算符:只要有一个是字符串,另一个也会转成字符串拼接

示例:

console.log(+true); // 1
console.log(1 + '2'); // '12'
console.log('3' + 4 + 5); // '345'
console.log(4 + 5 + '3'); // '93'

八、常见问题解答

  • 为什么对象和数组转布尔都是true?
    • 因为所有引用类型转布尔都为true
  • 为什么1 + '2'是'12',而'5' - 2是3?
    • +有拼接优先级,-只能做减法,自动转数字
  • 如何自定义对象的类型转换行为?
    • 可以重写toStringvalueOf方法
    • 当然可以!你可以在“六、隐式类型转换的常见场景”或“八、常见问题解答”部分,专门插入这个经典例子,并配上详细的拆解说明。下面是推荐的写法:

经典例子解析:1 == [] 为什么是 false?

你有没有想过,1 == [] 到底是 true 还是 false?很多初学者会觉得疑惑。我们来一步步拆解:

console.log(1 == []); // false

详细解析:

  1. == 遇到不同类型,会进行隐式类型转换。
  2. [] 是引用类型,和数字比较时,会先尝试把 [] 转成原始类型(ToPrimitive)。
  3. ToPrimitive([], Number) 的过程是:
    • 先调用 valueOf(),返回还是 [](不是原始类型)
    • 再调用 toString(),返回 ''(空字符串,是原始类型)
  4. 所以 1 == [] 实际变成了 1 == ''
  5. ''(空字符串)和数字比较时,'' 会被转成数字 0
  6. 最终比较的是 1 == 0,结果是 false

再看一个脑洞大开的例子:[] == ![] 为什么是 true?

你能猜到下面这行代码的结果吗?

console.log([] == ![]); // true

详细拆解:

  1. 先看右边的 ![][] 是对象,转布尔值为 true,取反后变成 false
  2. 所以表达式变成 [] == false
  3. == 比较时,false 会被转成数字 0
  4. 于是变成 [] == 0
  5. [] 和数字比较,会先转成原始类型(ToPrimitive),即 ''(空字符串)
  6. 变成 '' == 0
  7. 空字符串和数字比较,'' 会被转成数字 0
  8. 最终比较的是 0 == 0,结果为 true

九、总结

本文系统梳理了JS类型转换的核心原理、常见场景和易错点。建议大家多写代码、多调试,真正理解类型转换的底层逻辑。