你是否遇到过这样的疑惑:
- 为什么
1 == '1'是true,而1 === '1'却是false? - if语句、加号运算时,变量的类型怎么就悄悄变了?
obj + ''、+obj、Boolean(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]'
六、隐式类型转换的常见场景
-
四则运算:+ - * / %
+:只要有字符串,优先拼接- 其他运算符会把字符串转成数字
-
判断语句: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?+有拼接优先级,-只能做减法,自动转数字
- 如何自定义对象的类型转换行为?
- 可以重写
toString和valueOf方法 - 当然可以!你可以在“六、隐式类型转换的常见场景”或“八、常见问题解答”部分,专门插入这个经典例子,并配上详细的拆解说明。下面是推荐的写法:
- 可以重写
经典例子解析:1 == [] 为什么是 false?
你有没有想过,1 == [] 到底是 true 还是 false?很多初学者会觉得疑惑。我们来一步步拆解:
console.log(1 == []); // false
详细解析:
==遇到不同类型,会进行隐式类型转换。[]是引用类型,和数字比较时,会先尝试把[]转成原始类型(ToPrimitive)。ToPrimitive([], Number)的过程是:- 先调用
valueOf(),返回还是[](不是原始类型) - 再调用
toString(),返回''(空字符串,是原始类型)
- 先调用
- 所以
1 == []实际变成了1 == '' ''(空字符串)和数字比较时,''会被转成数字0- 最终比较的是
1 == 0,结果是false
再看一个脑洞大开的例子:[] == ![] 为什么是 true?
你能猜到下面这行代码的结果吗?
console.log([] == ![]); // true
详细拆解:
- 先看右边的
![],[]是对象,转布尔值为true,取反后变成false。 - 所以表达式变成
[] == false ==比较时,false会被转成数字0- 于是变成
[] == 0 []和数字比较,会先转成原始类型(ToPrimitive),即''(空字符串)- 变成
'' == 0 - 空字符串和数字比较,
''会被转成数字0 - 最终比较的是
0 == 0,结果为true
九、总结
本文系统梳理了JS类型转换的核心原理、常见场景和易错点。建议大家多写代码、多调试,真正理解类型转换的底层逻辑。