数据类型和转换
一、JavaScript 数据类型概述
JavaScript 是一种动态类型语言,变量无需预先声明类型,类型在运行时确定。其数据类型分为两类:
1. 原始数据类型(Primitive Types)
- Undefined:未初始化的变量默认值(
let x; console.log(x); // undefined
)。 - Null:表示空值(
const obj = null;
)。 - Boolean:
true
或false
。 - Number:整数和浮点数(
const num = 42; const pi = 3.14;
)。 - String:字符串(
const str = "Hello";
)。 - Symbol(ES6+):唯一标识符(
const id = Symbol("unique");
)。 - BigInt(ES10+):任意精度整数(
const big = 12345678901234567890n;
)。
2. 引用数据类型(Reference Types)
- Object:对象(
const person = { name: "John" };
)。 - Array:数组(
const arr = [1, 2, 3];
)。 - Function:函数(
function add(a, b) { return a + b; }
)。 - Date:日期对象(
const now = new Date();
)。 - RegExp:正则表达式(
const re = /abc/gi;
)。 - Error:错误对象(
const err = new Error("Something wrong");
)。
二、类型检测方法
方法 | 原始类型 | 引用类型 | 注意事项 |
---|---|---|---|
typeof | ✅(除 null) | 部分✅(如 function) | typeof null 返回 "object"(历史遗留问题) |
instanceof | ❌ | ✅ | 检测对象原型链(如 arr instanceof Array ) |
Object.prototype.toString.call() | ✅ | ✅ | 最准确的检测方式(如 [object String] ) |
Array.isArray() | ❌ | ✅(数组) | 专门检测数组 |
Symbol.prototype.description | ✅(Symbol) | ❌ | 获取 Symbol 描述 |
三、类型转换:隐式转换与显式转换
1. 隐式类型转换(自动转换)
JavaScript 会在特定操作中自动转换类型,可能导致意外结果。
-
字符串拼接(+):
1 + "2" // "12"(数字转字符串)
true + "false" // "truefalse"(布尔转字符串) -
算术运算(-、*、/):
"10" - 5 // 5(字符串转数字)
"abc" * 2 // NaN(无法转数字) -
布尔上下文(if、while 等):
if ("") { console.log("会执行吗?"); } // 不会,"" 转 false
if (0) { console.log("会执行吗?"); } // 不会,0 转 false
if (null) { console.log("会执行吗?"); } // 不会,null 转 false
if (undefined) { console.log("会执行吗?"); } // 不会,undefined 转 false
if ({}) { console.log("会执行吗?"); } // 会,对象转 true -
相等运算符(== 与 ===):
1 == "1" // true(隐式转换后比较)
1 === "1" // false(类型不同,直接不相等)
null == undefined // true(特殊情况)
2. 显式类型转换(手动转换)
-
转字符串(String() 或 toString()):
String(123) // "123"
(123).toString() // "123"(注意括号,避免语法错误)
true.toString() // "true" -
转数字(Number()、parseInt()、parseFloat()):
Number("123") // 123
parseInt("45px") // 45(只解析开头数字)
parseFloat("3.14cm") // 3.14
Number("abc") // NaN -
转布尔(Boolean()):
Boolean(0) // false
Boolean("") // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(NaN) // false
Boolean(1) // true
Boolean("abc") // true
Boolean({}) // true
四、特殊值与类型转换
-
NaN(Not a Number):
- 任何涉及非数字的算术运算都会返回 NaN(如
"abc" * 2
)。 NaN === NaN
返回false
,需用isNaN()
检测:isNaN(NaN) // true
isNaN("abc") // true
- 任何涉及非数字的算术运算都会返回 NaN(如
-
Infinity:
- 表示超出 JavaScript 数值范围的数(如
1 / 0
)。 - 分为
Infinity
(正数)和-Infinity
(负数)。
- 表示超出 JavaScript 数值范围的数(如
-
null 与 undefined:
null
是人为设置的空值,undefined
是未初始化的默认值。null
转数字为0
,undefined
转数字为NaN
:Number(null) // 0
Number(undefined) // NaN
五、类型转换的最佳实践
-
避免隐式转换:
- 使用严格相等运算符
===
而非==
,防止隐式转换导致的错误。
if (value === 0) { /* 处理 value 为 0 的情况 */ }
- 使用严格相等运算符
-
明确转换意图:
- 转数字时优先使用
parseInt/parseFloat
(保留整数部分或浮点精度):const str = "123.45";
parseInt(str) // 123
parseFloat(str) // 123.45
- 转数字时优先使用
-
空值处理:
- 用
nullish coalescing operator(??)
处理null
和undefined
:const value = userInput ?? "默认值"; // 若 userInput 是 null 或 undefined,使用默认值
- 用
-
布尔值转换技巧:
- 用
!!
快速转布尔:const isTrue = !!value; // 等价于 Boolean(value)
- 用
六、类型转换的性能考量
-
频繁转换:
避免在循环中进行大量类型转换(如字符串拼接),可预先转换:// 不好的写法
for (let i = 0; i < 10000; i++) {
result += i.toString(); // 每次循环都转换
}
// 优化写法
const strI = i.toString();
for (let i = 0; i < 10000; i++) {
result += strI; // 预先转换
} -
大数组转换:
使用map()
等数组方法批量转换,利用引擎优化:const numbers = ["1", "2", "3"];
const parsed = numbers.map(Number); // [1, 2, 3]
七、总结:类型转换的核心原则
- 理解自动转换规则:避免因隐式转换导致的逻辑错误(如
"" == false
为true
)。 - 使用严格比较:优先用
===
和!==
,明确类型一致性。 - 显式转换意图:用
String()
、Number()
等方法明确转换目的,提升代码可读性。 - 处理边界情况:特别注意
null
、undefined
、NaN
等特殊值的转换结果。