JavaScript 数据类型与隐式转换详解
一、JavaScript 数据类型
JavaScript 是弱类型语言,变量类型由值决定,主要分为以下类型:
-
原始类型(Primitive Types):
number
:数值(整数、浮点数、NaN
、Infinity
)。string
:字符串(如"hello"
)。boolean
:布尔值(true
/false
)。null
:空值。undefined
:未定义。symbol
(ES6+):唯一且不可变的值。bigint
(ES11+):大整数(如10n
)。
-
引用类型(Reference Types):
object
:对象(如{}
、[]
、Date
、函数等)。
二、隐式转换规则
JavaScript 在运算或逻辑判断中会自动进行类型转换,遵循以下规则:
1. 转换为 boolean
- 假值(Falsy):
false
、0
、""
(空字符串)、null
、undefined
、NaN
。 - 真值(Truthy):其他所有值(包括
"0"
、"false"
、空数组[]
、空对象{}
)。
if ("hello") {} // true(非空字符串)
if (0) {} // false
if ({}) {} // true(空对象是对象,存在即真)
2. 转换为 number
null
→0
undefined
→NaN
true
→1
,false
→0
- 字符串:空字符串
""
→0
,非数字字符串(如"123a"
)→NaN
。
Number("42") // 42
Number("42abc") // NaN
Number(true) // 1
Number(null) // 0
3. 转换为 string
null
→"null"
undefined
→"undefined"
- 布尔值 →
"true"
或"false"
。 - 对象:调用
toString()
方法(如[1,2].toString()
→"1,2"
)。
String(42) // "42"
String(true) // "true"
String([1,2]) // "1,2"
三、隐式转换场景与示例
1. +
运算符
- 规则:优先拼接字符串,若操作数中有字符串,则转为字符串拼接。
- 示例:
console.log(1 + "2"); // "12"(数字转字符串拼接) console.log(1 + 2 + "3"); // "33"(先计算 1+2=3,再拼接 "3") console.log("3" + 4 + 5); // "345"(从左到右拼接)
2. -
、*
、/
运算符
- 规则:优先转为数值运算。
- 示例:
console.log("5" - 2); // 3(字符串转数字) console.log("5" * "2"); // 10 console.log("abc" - 1); // NaN(无法转为数字)
3. ==
宽松相等比较
- 规则:触发隐式转换,可能导致意外结果。
- 示例:
console.log(1 == "1"); // true(字符串转数字) console.log(0 == false); // true(布尔值转数字) console.log("" == 0); // true(空字符串转 0) console.log(null == undefined); // true(特殊规则) console.log([] == 0); // true(空数组转空字符串→转 0)
4. 对象参与运算
- 规则:对象先调用
valueOf()
,若返回非原始值,再调用toString()
。 - 示例:
let obj = { valueOf: () => 42, toString: () => "hello" }; console.log(obj + 1); // 43(优先调用 valueOf)let arr = [1, 2]; console.log(arr + 3); // "1,23"(数组转字符串 "1,2")
5. 条件判断中的转换
- 示例:
if (0) { /* 不执行 */ } // 0 → false if ("hello") { /* 执行 */ } // 非空字符串 → true if ([]) { /* 执行 */ } // 空数组是对象 → true
四、常见陷阱与规避方法
1. NaN
的传染性
console.log(5 + NaN); // NaN(任何与 NaN 的运算结果都是 NaN)
console.log(NaN === NaN) // false(NaN 是唯一不等于自身的值)
2. null
和 undefined
的特殊性
console.log(null == 0); // false(null 只与 undefined 宽松相等)
console.log(undefined + 1); // NaN
3. 推荐使用严格相等(===
)
console.log(1 === "1"); // false(不触发类型转换)
console.log(0 === false); // false
4. 显式类型转换
// 转为数字
let num = +"42"; // 42
num = parseInt("42px"); // 42// 转为字符串
let str = 42 + ""; // "42"
str = String(42); // "42"// 转为布尔值
let bool = !!42; // true
五、总结
-
隐式转换规则:
+
优先拼接字符串,其他运算符优先转为数字。- 对象通过
valueOf()
和toString()
转换为原始值。 - 宽松相等(
==
)会触发复杂转换逻辑。
-
最佳实践:
- 使用
===
代替==
避免意外转换。 - 复杂运算时显式转换类型(如
Number()
、String()
)。 - 注意
NaN
、null
、undefined
的特殊行为。
- 使用
示例代码总结:
console.log(1 + "2"); // "12"
console.log("5" - 2); // 3
console.log([] == 0); // true(空数组 → "" → 0)
console.log({} + 1); // "[object Object]1"
console.log(Boolean("0")); // true(非空字符串为真)