第44课:JavaScript 数据类型(上)——string、number、boolean 与类型转换
JavaScript 有七种原始类型和一种对象类型。原始类型是不可变的、按值传递的;对象类型是可变的、按引用传递的。本节课聚焦于三种最基础、使用频率最高的原始类型——字符串(string)、数值(number) 和布尔值(boolean)。你将学习它们的字面量语法、常见操作、边界情况与陷阱,以及 JavaScript 中灵活且容易出错的显式与隐式类型转换机制。这是理解 == vs ===、表单输入处理、API 数据格式化等实际问题的前提。
1. string 类型:文本的表示与操作
字符串是不可变的、有序的 16 位无符号整数值序列,每个值对应一个 Unicode 字符(严格说是 UTF-16 代码单元)。
1.1 三种字面量语法
1 | const single = 'Hello'; // 单引号 |
| 语法 | 特性 | 适用场景 |
|---|---|---|
单引号 ' |
最简洁,内部可包含双引号无需转义。JSON 标准仅支持双引号。 | 常规字符串,风格偏好。 |
双引号 " |
内部可包含单引号无需转义。与 JSON 一致。 | 常规字符串,或包含英文缩写(如 It's)。 |
反引号 ` |
支持插值(${expression})和多行文本。 |
动态字符串拼接、多行文本、HTML 模板。 |
模板字符串的核心能力:
1 | const name = 'Alice'; |
1.2 不可变性
字符串一旦创建,其值就不能改变。所有“修改”字符串的操作实际都是返回一个新字符串。
1 | let str = 'Hello'; |
1.3 常用方法速览
| 方法 | 作用 | 返回值 |
|---|---|---|
length(属性) |
字符串长度(UTF-16 代码单元数量)。 | number |
charAt(index) |
返回指定索引的字符。 | string |
indexOf(sub) |
子串首次出现的索引,找不到返回 -1。 |
number |
includes(sub) |
是否包含子串(ES6)。 | boolean |
startsWith(sub) |
是否以子串开头。 | boolean |
endsWith(sub) |
是否以子串结尾。 | boolean |
slice(start, end) |
提取子串(支持负数索引)。 | string |
substring(start, end) |
提取子串(不支持负数,会自动交换参数)。 | string |
toLowerCase() |
转为全小写。 | string |
toUpperCase() |
转为全大写。 | string |
trim() |
去除首尾空白字符。 | string |
replace(old, new) |
替换首次匹配。 | string |
replaceAll(old, new) |
替换所有匹配(ES2021)。 | string |
split(sep) |
按分隔符拆分为数组。 | string[] |
1 | const email = ' Alice@Example.com '; |
2. number 类型:唯一的数值类型
JavaScript 只有一种数值类型:双精度 64 位 IEEE 754 浮点数。它统一了整数和小数,但也带来了精度问题。
2.1 数值范围与安全整数
1 | console.log(Number.MAX_VALUE); // 1.7976931348623157e+308 |
安全整数指可以精确表示和比较的整数范围。超过此范围的两个不同整数可能被表示为同一个浮点数。处理大整数时应使用 BigInt(第 45 课介绍)或将数值以字符串形式传递。
2.2 浮点数精度问题(经典陷阱)
1 | console.log(0.1 + 0.2); // 0.30000000000000004,不是 0.3 |
原因:0.1 和 0.2 在二进制中都是无限循环小数,IEEE 754 截断后存储的是它们的近似值,相加后再次截断,与 0.3 的近似值不相等。
解决方案:
- 使用容差值比较:
Math.abs(a - b) < Number.EPSILON。 - 将小数转为整数计算后还原(如金额用“分”为单位存储)。
- 使用第三方库(
decimal.js、big.js)。
1 | // 容差比较 |
2.3 特殊数值:NaN、Infinity、-Infinity
| 值 | 产生方式 | 特征 |
|---|---|---|
NaN |
0/0、parseInt('abc')、Number(undefined) |
表示“不是一个数字”,但 typeof NaN === 'number'。自身不等于自身:NaN !== NaN。 |
Infinity |
1/0、Number.POSITIVE_INFINITY |
正无穷大,任何正数除以 0 的结果。 |
-Infinity |
-1/0、Number.NEGATIVE_INFINITY |
负无穷大。 |
检测 NaN 的正确方式:
1 | // ❌ 错误:NaN 不等于自身 |
2.4 数值的显式转换与解析
| 方法 | 行为 | 示例 |
|---|---|---|
Number(value) |
严格转换,无法转换则返回 NaN。 |
Number('123') → 123、Number('12px') → NaN |
parseInt(str, radix) |
从左到右解析整数,遇到非数字字符停止。必须指定第二个参数(进制)。 | parseInt('12px', 10) → 12、parseInt('0xFF', 16) → 255 |
parseFloat(str) |
解析浮点数,只认第一个小数点。 | parseFloat('3.14.15') → 3.14 |
+value |
一元加号,等同于 Number(value)。 |
+'123' → 123 |
1 | // 常见场景:从 CSS 取值时去除单位 |
3. boolean 类型:只有 true 和 false
布尔值表示逻辑上的真与假,是条件判断和控制流的基础。
3.1 字面量与构造函数的区别
1 | const bool1 = true; // 原始布尔值 |
永远使用原始布尔值,避免 new Boolean()。
3.2 Falsy 值:8 个假值
在条件判断(if、while、!)或转换为布尔值时,以下 8 个值被视为 false,其余所有值都是 true:
| Falsy 值 | 说明 |
|---|---|
false |
布尔假值本身。 |
0、-0 |
数字零和负零。 |
0n |
BigInt 零。 |
''、""、 |
空字符串。 |
null |
空值。 |
undefined |
未定义。 |
NaN |
非数字。 |
常见的 Truthy 但容易误判为假的值:
- 字符串
'false'、'0'、' '(空格)—— 非空字符串都是 truthy。 - 空数组
[]、空对象{}。 new Boolean(false)(任何对象都是 truthy)。
1 | const userInput = ''; // 空字符串 |
4. 显式类型转换:主动控制类型
JavaScript 提供了多种显式转换类型的方法,这是编写健壮代码的基础。
4.1 转字符串:String() 与 .toString()
1 | String(123); // '123' |
String() 是全局函数,能安全处理 null 和 undefined。.toString() 是原型方法,对 null/undefined 调用会抛出异常。
4.2 转数值:Number()、parseInt()、parseFloat()
已在 2.4 节详述。补充对比表:
| 输入 | Number(input) |
parseInt(input, 10) |
|---|---|---|
'42' |
42 |
42 |
'42px' |
NaN |
42 |
'' |
0 |
NaN |
' 42 ' |
42 |
42 |
true |
1 |
NaN |
null |
0 |
NaN |
undefined |
NaN |
NaN |
4.3 转布尔值:Boolean() 与 !!
1 | Boolean(1); // true |
5. 隐式类型转换:== 与 + 的规则
JavaScript 在特定操作符下会自动将操作数转换为期望的类型。理解这些规则是规避 Bug 的关键。
5.1 加法运算符 + 的特殊性
+ 既是数值加法,也是字符串连接。当任一操作数是字符串时,另一个也会被转为字符串。
1 | console.log(1 + 2); // 3(数值加法) |
5.2 宽松相等 == 与严格相等 ===
== 在比较前会进行类型转换,规则复杂且容易出错。=== 不转换类型,类型不同直接返回 false。
1 | // == 的隐式转换陷阱 |
实践原则:始终使用 ===(严格相等),除非你明确需要 null == undefined 这种特殊行为(例如同时检查一个变量是否为 null 或 undefined)。
5.3 比较运算符 <、> 的转换
当两个操作数都是字符串时,按字典序比较;否则尝试转为数值比较。
1 | console.log('10' > 2); // true —— '10' 转为 10 |
课后练习
一、概念自测(选择题 / 填空题)
(单选)
0.1 + 0.2 === 0.3的结果是?
A.true
B.false
C.TypeError
D.NaN(单选) 以下关于
NaN的说法,正确的是?
A.typeof NaN === 'NaN'
B.NaN === NaN返回true
C.Number.isNaN('abc')返回true
D.NaN是唯一一个不等于自身的 JavaScript 值(填空) 在 JavaScript 中,空数组
[]转换为布尔值时是______(true/false)。(多选) 以下哪些值在条件判断中是 falsy(假值)?
A.0
B.'false'
C.''
D.undefined
二、AI 编程任务:编写面向 AI 的提示词
场景:你需要编写一个 JavaScript 工具函数 safeAdd,用于安全地将两个任意类型的值相加并返回字符串结果。要求如下:
- 如果两个参数都是数字(或能安全转换为有意义数字的字符串),返回它们的算术和转为字符串。
- 如果任一参数转换数字失败(如
'abc'),则将二者都转为字符串进行拼接。 - 需要处理
null、undefined、boolean等边界情况。 - 使用
const声明函数,内部变量优先const,需要重新赋值时用let。 - 添加 JSDoc 注释,说明参数类型、返回值和转换逻辑。
- 提供至少 5 个测试用例的输出注释。
任务要求:请写出一段完整的中文提示词,发送给 AI,使其生成符合上述要求的 JavaScript 代码。提示词中需明确指定类型转换的判断逻辑(如何使用 Number() 和 isNaN())、命名规范和代码风格。
课后练习答案
一、概念自测答案
B
- 解析:IEEE 754 浮点数精度问题,
0.1 + 0.2的结果是0.30000000000000004。
- 解析:IEEE 754 浮点数精度问题,
D
- 解析:A 错误,
typeof NaN === 'number';B 错误,NaN !== NaN;C 错误,Number.isNaN不会先转换类型,'abc'不是NaN值本身。
- 解析:A 错误,
true- 解析:空数组是对象(
typeof [] === 'object'),所有对象在布尔上下文中都是 truthy。
- 解析:空数组是对象(
A、C、D
- 解析:
0、''、undefined都是 falsy 值。'false'是非空字符串,是 truthy。
- 解析:
二、AI 编程任务参考答案(提示词示例)
示例提示词:
“请编写一个 JavaScript 函数safeAdd(a, b),安全地将两个任意类型的值相加并返回字符串。要求:
- 函数使用
const声明。内部变量优先const,需要重新赋值时用let,不使用var。- 转换逻辑:使用
Number(a)和Number(b)尝试转为数字。若两者转换后都不是NaN(用!Number.isNaN()判断),则返回(数值a + 数值b).toString()。否则,使用String(a) + String(b)进行字符串拼接。- 处理边界:
null转为数字是0,undefined转为数字是NaN,true→ 1,false→ 0。- 添加 JSDoc 注释(@param、@returns、@description)。
- 在代码底部使用注释提供至少 5 个测试用例及其预期输出(例如
safeAdd(1, 2) // '3'、safeAdd('1', '2') // '3'、safeAdd('a', 1) // 'a1'、safeAdd(null, 5) // '5'、safeAdd(undefined, 5) // 'undefined5')。- 代码简洁,遵循 Airbnb 风格指南。直接输出完整代码。”