一、JavaScript 中的七种基本数据类型
JavaScript 是一门弱类型语言,这意味着你不需要在声明变量时指定其类型,变量的类型会根据赋值自动判断。JS 中有 7 种原始数据类型(Primitive Types) 和一种引用类型(Object):
原始类型(Primitive Types)
undefined—— 未定义null—— 空对象引用boolean—— 布尔值(true / false)number—— 数字(整数和浮点数)string—— 字符串symbol—— ES6 引入的唯一标识符bigint—— ES2020 引入的大整数类型
引用类型(Reference Type)
object—— 对象、数组、函数等都属于 object 类型
二、类型转换详解:隐式 vs 显式
JavaScript 在运行过程中常常需要进行类型转换(Type Coercion),这是 JS 的一大特性,也是很多“坑”的来源。
1. 显式类型转换(Explicit Coercion)
显式类型转换是通过构造函数或全局函数手动完成的:
Boolean(0); // false
Number("123"); // 123
String(123); // "123"
🌫️ 2. 隐式类型转换(Implicit Coercion)
隐式类型转换发生在运算过程中,例如:
"123" + 1; // "124" (字符串拼接)
"123" - 1; // 122 (减法强制转为数字)
if ("hello") {} // true (条件判断中非空字符串视为 true)
三、常见类型转换案例解析
我们来结合具体例子分析不同类型的转换行为。
1. undefined 转换
| 表达式 | 结果 | 说明 |
|---|---|---|
| Boolean(undefined) | false | 所有 undefined 都会被转为 false |
| Number(undefined) | NaN | 无法转为有效数字 |
| String(undefined) | 'undefined' | 直接转为字符串 |
2. null 转换
| 表达式 | 结果 | 说明 |
|---|---|---|
| Boolean(null) | false | null 表示空值 |
| Number(null) | 0 | 特殊处理,null 被认为是 0 |
| String(null) | 'null' | 转为字符串形式 |
3. boolean 转换
| 表达式 | 结果 | 说明 |
|---|---|---|
| Number(true) | 1 | true = 1, false = 0 |
| Number(false) | 0 | 同上 |
| String(true) | 'true' | 转为字符串形式 |
4. number 转换
| 表达式 | 结果 | 说明 |
|---|---|---|
| Boolean(0) | false | 0 为假值 |
| Boolean(1) | true | 非零为真 |
| String(123) | '123' | 正常转换 |
| String(NaN) | 'NaN' | NaN 也会被转为字符串 |
5. string 转换
| 表达式 | 结果 | 说明 |
|---|---|---|
| Number('123') | 123 | 可以正常转换 |
| Number('abc') | NaN | 不能转为数字 |
| Boolean('') | false | 空字符串为假 |
| Boolean(' ') | true | 有空格也为真 |
6. symbol 转换
| 表达式 | 结果 | 说明 |
|---|---|---|
| String(Symbol('a')) | 'Symbol(a)' | symbol 可以转为字符串 |
| Number(Symbol()) | 报错 | 不允许转为数字 |
| Boolean(Symbol()) | true | symbol 永远为真 |
7. object 转换
对象会调用自身的 toString() 或 valueOf() 方法尝试转换:
Number({}); // NaN
String({}); // "[object Object]"
Boolean({}); // true
四、map API 使用详解:优雅地处理数组
Array.prototype.map() 是数组的一个非常常用的高阶函数,它会创建一个新数组,其结果是对原数组中的每个元素执行一次回调函数后的返回值。
语法:
arr.map(function callback(currentValue, index, array) {
return element for new array;
}, thisArg);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
currentValue | any | 当前正在处理的元素 |
index | number | 当前索引 |
array | array | 调用 map 的数组本身 |
thisArg | any | 可选参数,执行 callback 时使用的 this 值 |
示例:
const numbers = [1, 2, 3];
const squares = numbers.map(n => n * n); // [1, 4, 9]
更复杂一点的例子:
const users = [
{ name: "Tom", age: 20 },
{ name: "Jerry", age: 25 }
];
const names = users.map(user => user.name); // ["Tom", "Jerry"]
注意事项:
map不会修改原数组,而是返回一个新数组。- 如果不写
return,新数组中对应位置的值将是undefined。 map不能跳过某些元素,除非你返回undefined或使用filter配合使用。
五、parseInt API 深度剖析:不只是“转成数字”
parseInt(string, radix) 函数用于将字符串解析为整数。很多人只知道它可以“把字符串变成数字”,但它的第二个参数 radix(进制)经常被忽略,导致一些令人困惑的结果。
语法:
parseInt(string, radix)
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
string | string | 要解析的字符串 |
radix | number | 进制数(2 到 36),可选 |
示例讲解:
示例 1:默认进制
parseInt("10"); // 10(十进制)
parseInt("10", 10); // 10(明确十进制)
示例 2:八进制陷阱(ES5 之前)
parseInt("010"); // 8(ES3 时期,前缀 0 表示八进制)
parseInt("010", 10); // 10(建议始终指定进制)
ES5 开始,
parseInt("010")返回10,不再默认识别八进制,但仍建议传入radix。
示例 3:十六进制
parseInt("FF", 16); // 255
示例 4:混合字符
parseInt("123px"); // 123(只取前面的数字部分)
parseInt("abc123"); // NaN(没有开头数字)
🧠 常见误区总结:
parseInt("1.5")→1(只会取整数部分)parseFloat("1.5")→1.5(更推荐用于浮点数)- 忘记传
radix导致意想不到的结果 - 处理非字符串输入时出错(如
parseInt(null))
六、实战场景:map + parseInt 的组合使用
我们来看一个常见的错误场景:
['1', '2', '3'].map(parseInt);
// 输出: [1, NaN, NaN] ??? 为什么?
问题分析:
这是因为 map 传递给 parseInt 的参数顺序是:
parseInt(currentValue, index, array)
而 parseInt 的第二个参数是 radix,所以当 index 是 0、1、2 时:
parseInt('1', 0) → 1(radix=0 退化为 10)
parseInt('2', 1) → NaN(进制必须是 2~36)
parseInt('3', 2) → NaN('3' 不是二进制合法字符)
正确写法:
['1', '2', '3'].map(Number); // 推荐方式
// 或
['1', '2', '3'].map(str => parseInt(str, 10));
七、总结:掌握类型转换,写出更健壮的代码
JavaScript 的类型系统虽然灵活,但也带来了许多“惊喜”。理解这些类型之间的转换规则,能帮助你写出更稳定、更少 bug 的代码。
- 学会区分原始类型与引用类型
- 掌握类型转换的基本逻辑与边界情况
- 熟练使用
map来优雅处理数组 - 懂得正确使用
parseInt,避免常见误解
结语
JavaScript 的魅力就在于它的灵活性和多样性。虽然类型转换有时会让人头疼,但正是这种“松散”的设计让 JS 成为了 Web 的核心语言之一。
希望这篇文章能让你对 JavaScript 的类型系统有一个更清晰、更深入的理解。如果你是初学者,不妨多动手实践,尝试不同类型之间的转换;如果你已经是老手,也可以温故知新,看看有没有新的发现!
欢迎留言交流你在项目中遇到的类型转换“踩坑”经历,我们一起学习成长!