主题
类型转换
提示
JavaScript 是一种弱类型语言,这意味着变量没有固定的类型,值可以在不同类型之间自动转换。理解类型转换机制(尤其是隐式转换)对于编写健壮的代码至关重要。
类型转换主要分为显式类型转换和隐式类型转换。
1. 抽象操作 (Abstract Operations)
在了解具体的转换规则前,我们需要先了解 ECMAScript 规范中定义的几个内部抽象操作。
ToPrimitive
将引用类型转换为基本类型。
转换规则:
- 检查对象是否有
Symbol.toPrimitive方法。如果有,调用它。 - 如果没有,检查是否有
valueOf()方法。如果是基本类型值,返回它。 - 如果没有
valueOf或返回的不是基本类型,调用toString()。如果是基本类型值,返回它。 - 如果都没有返回基本类型,抛出
TypeError。
注意:对于
Date对象,默认优先调用toString()。
js
const obj = {
valueOf() {
return 100
},
toString() {
return 'obj'
},
}
console.log(Number(obj)) // 100 (valueOf)
console.log(String(obj)) // 'obj' (toString)ToString
将非字符串值转换为字符串。
| 输入类型 | 转换结果 |
|---|---|
undefined | 'undefined' |
null | 'null' |
true / false | 'true' / 'false' |
Number | '123', 'NaN', 'Infinity' |
Object | 先 ToPrimitive,再 ToString |
ToNumber
将非数字值转换为数字。
| 输入类型 | 转换结果 |
|---|---|
undefined | NaN |
null | 0 |
true / false | 1 / 0 |
String | '123' -> 123, '' -> 0, 'abc' -> NaN |
Object | 先 ToPrimitive,再 ToNumber |
ToBoolean
将值转换为布尔值。
假值 (Falsy Values):
undefinednullfalse+0,-0,NaN""(空字符串)
真值 (Truthy Values):
- 除上述假值以外的所有值(包括空对象
{}和空数组[])。
2. 显式类型转换
显式调用函数进行转换,代码意图清晰。
转换为字符串
String(value)value.toString()
转换为数值
Number(value)parseInt(string, radix)parseFloat(string)
转换为布尔值
Boolean(value)!!value(双重取反,虽然是操作符但常用于显式转换)
3. 隐式类型转换
发生在运算符操作或流程控制语句中,容易产生意想不到的结果。
四则运算符
加法 (+):
- 如果有一个操作数是字符串,则进行字符串拼接(另一个操作数也会被转为字符串)。
- 否则,进行数字加法(将操作数转为数字)。
js
1 + '1' // '11'
1 + true // 2
1 + null // 1
1 + undefined // NaN减、乘、除 (-, *, /):
- 都会将操作数转换为数字进行运算。
js
'5' - '2' // 3
'5' * '2' // 10
'5' / '2' // 2.5相等运算符 (==)
== 会进行类型转换后再比较,规则较为复杂(建议优先使用 ===)。
核心规则:
null == undefined// trueString == Number->ToNumber(String) == NumberBoolean == Any->ToNumber(Boolean) == AnyObject == String/Number->ToPrimitive(Object) == String/Number
经典面试题:
js
;[] == ![] // true解析:
![]转换为false。[] == false。false转换为0。[] == 0。[]ToPrimitive 转换为'',再 ToNumber 转换为0。0 == 0->true。
关系运算符 (>, <)
- 如果两个操作数都是字符串,比较 Unicode 编码。
- 否则,转换为数字比较。
js
'10' < '9' // true (因为 '1' 的编码 < '9')
'10' < 9 // false (10 < 9)4. 总结与建议
- 尽量使用显式转换:如
Number(),String(),让代码意图更明确。 - 使用
===代替==:避免隐式转换带来的不可预期结果。 - 注意
if判断:直接使用if (obj)时,利用的是ToBoolean规则。
