主题
数据类型转换(Day2 2/4)
本页对应 Day02_JavaScript,共 6 段视频,约 1 小时 5 分。
学习目标
- 能针对给定参数分别写出
Number、parseInt、parseFloat的返回值,并说明非字符串、纯数字字符串、以数字开头字符串、空字符串、带空格字符串、十六进制和科学计数法等情形下的转换差异。 - 能判断算术运算中是否发生自动类型转换,并按与
Number一致的规则写出布尔值、字符串等参与运算后的结果。 - 能识别表达式中的运算符与操作数,判断表达式是否有值、值的数据类型,并说明原始表达式和副作用的含义。
- 能按操作数个数将运算符分为一元、二元、三元,按功能分为算术、关系、逻辑、位、赋值和其他运算符,并各举一例。
- 能对
+ - * / %及一元正负号写出操作数个数、类型要求、表达式值类型和有无副作用,并计算给定表达式的值。 - 能计算包含
++、--前置和后置的表达式值与变量最终值,说明副作用相同但表达式值不同,并判断直接量使用++、--会报错。
知识点
回顾的目标:把零散知识点串成可验证的规则
这一节叫“回顾”,不是重新背概念,而是把“怎么引入 JS、怎么写基本语法、怎么声明变量、怎么判断数据类型”串成一套能上机验证的规则。转写稿里反复强调一个思路:不要凭感觉记,写个案例看结果;同时要区分“表达式的值”和“操作数本身有没有变”。这个思路同样适合回顾数据类型。
在HTML中使用JS
为什么需要:JS 不能凭空运行,必须先挂到 HTML 文档里,浏览器才知道什么时候执行。
怎么想:先确定脚本放在哪里、是内联还是外链,再考虑执行顺序。
怎么做:用 <script> 标签写 JS;外链用 src 引入;调试输出优先用 console.log()。
易错点:src 引入后标签内的代码通常不再执行;脚本位置会影响它能否拿到后面的 DOM。
JS基本语法
为什么需要:语法是后面所有代码的地基,语句边界、大小写、注释、输出方式都必须清楚。
怎么想:把“语句结束符、大小写、注释、输出”当成四件独立的事逐项检查。
怎么做:语句结束可用分号或换行;JS 严格区分大小写;单行注释 //,多行注释 /* */;输出可用 alert()、document.write()、console.log()。
易错点:依赖换行在压缩、拼接时可能出问题,初学建议写分号;document.write() 会往文档流里写内容,调试更适合 console.log();变量 age 和 Age 是两个名字。
变量
为什么需要:数据要反复使用,就必须有名字保存,否则每次都要重新写字面量。
怎么想:先声明,再赋值,再使用;名字要能表达含义。
怎么做:例如 var age = 18;,先声明变量再参与运算。命名按课程约定:不能以数字开头,不能使用关键字,区分大小写,建议用驼峰命名。
易错点:未声明直接使用;把关键字当变量名;大小写写错导致“变量不存在”。
数据类型与typeof
为什么需要:同样是“1”,可能是数字,也可能是字符串;类型不同,运算结果就不同。
怎么想:先用 typeof 看类型,再看值是否符合预期。
怎么做:typeof 123 得到 "number",typeof "123" 得到 "string",typeof true 得到 "boolean"。
易错点:typeof null 返回 "object",这是历史遗留问题,不能据此认为 null 是对象;typeof 看的是“当前值”的类型,不是转换后的类型。
number类型
为什么需要:数值要支持整数、小数、科学计数法,还要表示“不是有效数字”的情况。
怎么想:先判断是不是合法数字,再判断是否超出有效范围,最后看特殊值 NaN。
怎么做:整数、浮点、科学计数法都属 number;NaN 的类型也是 number;有效范围可查 Number.MAX_VALUE、Number.MIN_VALUE,整数精度可关注安全整数范围。
易错点:NaN 不等于任何值,包括它自己;判断可用 isNaN();浮点数相加可能出现精度问题。
string类型
为什么需要:文本是最常见的数据,必须能表示引号、换行等特殊字符。
怎么想:先选单引号或双引号,再处理内部引号和转义。
怎么做:'abc'、"abc" 都可以;转义用反斜杠,如 \'、\"、\n。
易错点:单引号字符串里直接写单引号会提前结束;引号必须成对;字符串 "123" 不是数字。
boolean、null和undefined
为什么需要:程序要表达“真/假”“空值”“未赋值”等状态。
怎么想:boolean 只有 true 和 false;null 表示“空”,undefined 表示“未定义/未赋值”。
怎么做:用 typeof 验证:typeof true 是 "boolean",typeof undefined 是 "undefined",typeof null 是 "object"。
易错点:不要把 null 和 undefined 混为一谈;typeof null 的返回值容易误导。
用控制台做一次回顾调试
转写稿里讲 parseInt、parseFloat 和自动类型转换时,核心提醒是:转换规则要看转换函数,不要凭感觉。回顾数据类型时也可以这样验证:
js
console.log(typeof 123); // "number"
console.log(typeof "123"); // "string"
console.log(Number("")); // 0
console.log(parseInt("45ABC")); // 45
console.log(parseInt("hello100")); // NaN
console.log(parseInt(23.89)); // 23转写稿里说的“pas in”就是 parseInt,“pass float”就是 parseFloat。它们不是标准类型转换函数,本意是“提取字符串中的数字”:非字符串如 true、false、null、undefined 往往得到 NaN;空字符串也提取不到数字,得到 NaN;parseInt 只取整数部分,且直接去掉小数,不四舍五入。自动类型转换的规则则与 Number 一致,而不是与 parseInt 一致。调试时先看 typeof 原值,再看转换结果,就不容易把“值变了”和“只是参与运算时临时转换”混在一起。
说明:本节笔记未附图片;下面保留并整理转写稿中的代码,同音字已改为 parseInt、parseFloat、Boolean、console.log 等正确写法。
一、显式转换:Number、String、Boolean
为什么需要:当类型不一致时,需要明确告诉浏览器“把数据转成目标类型”。
怎么想:看到转换函数就知道目标类型:Number 转数字,String 转字符串,Boolean 转布尔。
怎么做:
js
Number(true); // 1
Number(false); // 0
Number(""); // 0
Number("abc"); // NaN易错点:Number 是标准强制转换函数;自动类型转换转数字时,规则与 Number 一致,而不是与 parseInt、parseFloat 一致。
二、parseInt 与 parseFloat:提取字符串中的数字
为什么需要:Number("45ABC") 会得到 NaN,但有些场景只想提取开头的数字。
怎么想:它们的本意是“从字符串中提取数字”。非字符串参数先全部得到 NaN;纯数字字符串或以数字开头的字符串才可能转成有效数字。
怎么做:
js
parseInt("45ABC"); // 45
parseInt("hello100"); // NaN
parseInt("23.89ABC"); // 23
parseFloat("23.89ABC"); // 23.89
parseInt(3.14); // 3
parseInt(" 23 "); // 23
parseInt(""); // NaN
parseInt(true); // NaN易错点:parseInt 只取整数部分,直接截掉小数,不四舍五入;空字符串是 NaN,不是 0;非字符串如 true、false 也是 NaN。调试时可用 console.log 分别看 parseInt 和 parseFloat 的结果。
三、自动类型转换
为什么需要:运算符需要特定类型的数据,而 JS 允许在运算时自动转换。
怎么想:先看当前运算环境需要什么类型,这通常由运算符决定;不是所需类型,就自动转换。
怎么做:
js
true * 67; // 67
"60" * false; // 0
"hello" * false; // NaN易错点:自动转换不是副作用,操作数本身没有变,只是转成所需类型后参与运算;转数字规则与 Number 一致,不要混用 parseInt 的规则。
四、表达式、运算符、操作数
为什么需要:读代码、讲代码时经常说“这个表达式的值”,必须明确概念。
怎么想:运算符是参与运算的符号;操作数是与运算符一起运算的变量、直接量或数据;数据和运算符共同组成表达式,表达式有计算结果,叫表达式的值。
怎么做:
js
1 + 1; // 表达式,有值变量、直接量也可算原始表达式;多个简单表达式可组成复杂表达式。
易错点:表达式一定有值;运算符是表达式的核心,决定怎么算、结果是什么类型、有没有副作用。
五、运算符分类与算术运算符
为什么需要:按功能学比按符号死记更清楚。
怎么想:可按操作数个数分一元、二元、三元;JS 中三元运算符只有一个,后面再讲。学习时按功能分:算术、关系、逻辑、位、赋值、其他。
怎么做:
js
45 % 10; // 5
50 % 10; // 0加减乘除和取余通常要求操作数为 number,表达式值也是 number,且无副作用。
易错点:% 是取余,不是百分比;正号和负号是一元运算符,加号和减号是二元运算符,写法相同要看操作数个数。
六、正负号:看表达式的值,不改变操作数
为什么需要:初学容易把“表达式结果”误认为“操作数被改了”。
怎么想:+true 得到的是表达式的值 1,但 true 本身仍是 true。
怎么做:
js
+89; // 89
+true; // 1
let v1 = false;
console.log(+v1); // 0
console.log(v1); // false
let v2 = -89.12;
console.log(+v2); // -89.12
console.log(-v1); // -0,等价于 0
console.log(-v2); // 89.12易错点:正号不会把负数变正;负号也没有修改 v2,v2 仍是 -89.12;正负号表达式无副作用。
七、累加累减与副作用
为什么需要:++、-- 是编程中特有的写法,会真正改变变量。
怎么想:副作用是“除了得到表达式结果,还修改参与运算的操作数”;有副作用时,操作数必须是变量。
怎么做:
js
let num = 18;
num++;
console.log(num); // 19
++num;
console.log(num); // 20
--num;
console.log(num); // 19
num--;
console.log(num); // 18易错点:5++ 会报错,因为直接量不能被重新赋值;前后缀的副作用一样,都是让变量加一或减一,不同的是表达式的值。
八、前后缀表达式值与复杂表达式调试
为什么需要:考试和调试常把“变量当前值”和“表达式的值”混在一起。
怎么想:后缀 v++ 先取旧值作为表达式值,再让变量加一;前缀 ++v 先让变量加一,再取新值作为表达式值。
怎么做:
js
let v1 = 10;
console.log(v1++); // 10
console.log(v1); // 11
let v2 = 10;
console.log(++v2); // 11
console.log(v2); // 11
let v3 = 10;
console.log(v3--); // 10
console.log(v3); // 9
let v4 = 10;
console.log(--v4); // 9
console.log(v4); // 9复杂表达式要从左到右算,每一步记录副作用:
js
let number = 10;
let res = number++ - number-- + ++number - --number + number++;
console.log(res, number);易错点:不能一直用初始值算后面的部分;前面的 number++ 已改变 number,后面要用改变后的值;调试时先输出表达式值,再输出变量,观察副作用。
课堂画面






代码示例
示例一:parseInt / parseFloat 与 Number 的区别
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>parseInt / parseFloat 提取字符串中的数字</title>
</head>
<body>
<script>
// 1. 参数不是字符串:parseInt / parseFloat 一律返回 NaN
console.log(parseInt(true)); // NaN (Number(true) 是 1)
console.log(parseInt(false)); // NaN (Number(false) 是 0)
console.log(parseInt('')); // NaN (Number('') 是 0)
console.log(parseInt(NaN)); // NaN
// 2. 字符串:纯数字、或以数字开头的字符串,都能提取出有效数字
console.log(parseInt('123')); // 123
console.log(parseInt('45ABC')); // 45 (Number('45ABC') 是 NaN)
console.log(parseInt('hello100')); // NaN (不是以数字开头)
console.log(parseInt('0xAB')); // 171 (十六进制)
console.log(parseInt('28e4')); // 28 (只提取 e 前面的整数部分)
console.log(parseInt(' 23 ')); // 23 (会去掉两边空格)
// 3. parseInt 与 parseFloat 的区别:一个只取整数,一个取所有数字
console.log(parseInt('23.89ABC')); // 23
console.log(parseFloat('23.89ABC')); // 23.89
// 4. parseInt 的常用技巧:直接取数字的整数部分
console.log(parseInt(3.14)); // 3 (直接把小数部分去掉,不四舍五入)
</script>
</body>
</html>要点解释
parseInt/parseFloat的本意是“从字符串中提取数字”,所以参数不是字符串时一律 NaN,这点和Number完全不同(Number(true)=1、Number('')=0)。- 能提取的前提是:纯数字字符串,或以数字开头的字符串。
'45ABC'能得 45,'hello100'只能得 NaN。 parseInt('23.89')得到 23,是直接截掉小数,不是四舍五入;要小数位就用parseFloat。parseInt(3.14)参数传数字也能用,常用来取整;parseInt(' 23 ')会去掉两边空格。- 易错点:
parseInt('')是NaN,而Number('')是0;别把两者的规则记混。
示例二:自动类型转换、取余与一元正负号
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>自动类型转换与算术运算符</title>
</head>
<body>
<script>
// 1. 自动类型转换:运算符需要 number,操作数不是 number 就自动转
console.log(true * 67); // 67 true → 1
console.log('60' * false); // 0 '60' → 60,false → 0
console.log('hello' * false); // NaN 'hello' → NaN,NaN 参与运算还是 NaN
// 2. 取余 %(不是百分比),常用来判断能不能被整除
console.log(45 / 10); // 4.5 商
console.log(45 % 10); // 5 余数
console.log(50 % 10); // 0 余数为 0 说明能整除
// 3. 一元正负号:有表达式的值,但【没有副作用】,操作数本身不变
let v1 = false;
console.log(+true); // 1
console.log(+v1); // 0
console.log(v1); // false ← 变量本身没被改变
let v2 = -89.12;
console.log(+v2); // -89.12 正号不改变正负
console.log(-v2); // 89.12
console.log(v2); // -89.12 ← 变量本身还是负数
console.log(-v1); // -0
// 4. 加号/减号是“正负号”还是“加减”:看操作数个数
console.log(+89); // 89 1 个操作数 → 一元正号
console.log(1 + 2); // 3 2 个操作数 → 二元加法
</script>
</body>
</html>要点解释
- 自动类型转换:数据不是当前运算环境需要的类型时自动转换,转换规则与强制类型转换(
Number)一致,和parseInt/parseFloat不一致。 - 转换发生在“参与运算”这一步,操作数本身没变,所以自动类型转换不算副作用;
+v1输出 0,但v1依然是false。 %是取余不是百分比,余数为 0 表示能整除,这是开发中最常用的判断方式。- 一元正负号只是“把操作数加上符号”产生一个新的表达式值,不会把变量改成相反数;
+也不会把负数变正。 - 易错点:不要把“表达式的值”当成“变量的值”来看,
+true是 1,但true本身还是true。
示例三:累加累减的副作用与表达式的值
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>累加累减:副作用与表达式的值</title>
</head>
<body>
<script>
// 1. 副作用:除了算出表达式的结果,还把操作数本身改了
let num = 18;
num++;
console.log(num); // 19
++num;
console.log(num); // 20
num--;
console.log(num); // 19
// 2. 有副作用的表达式,操作数必须是变量;直接量会报错
// 5++; // 报错:不能给直接量重新赋值,一就是一二就是二
// 3. 操作数不是 number 会先转再算,但变量本身被改成了 number
let v = true;
v++;
console.log(v); // 2 (对比示例二的 +true:变量不会变)
// 4. ++ / -- 在前在后:副作用一样,表达式的值不一样
let v1 = 10;
console.log(v1++); // 10 操作数在前:先取值当表达式的值,再自增
console.log(v1); // 11
let v2 = 10;
console.log(++v2); // 11 运算符在前:先自增,用自增后的值当表达式的值
console.log(v2); // 11
let v3 = 10;
console.log(v3--); // 10
let v4 = 10;
console.log(--v4); // 9
// 5. 复杂表达式:从左到右依次计算,每步副作用都会改变 number,
// 后面的运算必须用“改过之后”的值,不能一直按 10 算
let number = 10;
let res = (number++) - (number--) + (++number) + (--number) + (number++);
console.log(res); // 整个表达式的值
console.log(number); // 经历多步副作用之后,变量的值
</script>
</body>
</html>要点解释
- 累加累减是目前见到的第一个有副作用的运算符:除了得到表达式的值,还会修改操作数本身。
- 有副作用的表达式要求操作数必须是变量形式,写
5++会报错——直接量没法被重新赋值。 ++/--在前在后,副作用完全相同(都是给操作数加一或减一),不一样的只是表达式的值:操作数在前先取值、运算符在前先运算。- 判断“谁在前”的口诀:操作数在前 → 用没变之前的值当表达式值;运算符在前 → 用变完之后的值当表达式值。
- 复杂表达式要从左往右算,前一步的副作用会影响后一步的取值,这是最容易算错的地方。
- 易错点:不要把
+true(无副作用,变量还是true)和v++(有副作用,变量被改成 number)混为一谈。
常见错误
现象:把
parseInt当成通用数字转换函数,遇到true、null、undefined期望得到1/0。
原因:混淆了parseInt/parseFloat与Number的转换规则。
修法:先明确目标是“提取数字”还是“整体转数字”;需要整体转换时优先用Number()。现象:认为
parseInt("12.9")会四舍五入,或认为parseFloat("12.9px")会报错。
原因:把数学取整、严格转换和“从头提取数字”混为一谈。
修法:写小案例验证parseInt、parseFloat、Number三者的差异,按业务选择。现象:自动类型转换时凭感觉猜结果,尤其遇到
+、true、false、字符串。
原因:没有先判断当前运算符要求什么类型,也没有区分一元+和二元+。
修法:先看运算符和上下文,再按Number规则推演;不确定就打印中间值。现象:
let v = false; v++;后仍以为v是false。
原因:忽略自增自减的副作用,或把“表达式值”和“变量值”混在一起。
修法:分别输出变量本身和表达式结果,明确副作用是否改变操作数。现象:
let a = 1; console.log(a++ + ++a);算错,且没有跟踪a的中间变化。
原因:只看最终表达式,没有按从左到右顺序记录副作用。
修法:每算一步就更新变量值,并标注该步表达式返回的是旧值还是新值。现象:写
5++、++(a + b)之类代码,期望修改变量。
原因:不知道有副作用的表达式要求操作数是变量。
修法:把自增自减只用于可修改的变量;复杂表达式先拆成多步。
练习
- 分别写出下列表达式的结果,并说明理由:
Number("")、parseInt("")、parseFloat("12.3px")、parseInt("0x10")、Number("0x10")。 - 判断并写出输出:
console.log(true * "6", "hello" * false, false + 1, "2" + 1)。 - 阅读代码并写出两次输出及最终
a的值:let a = 10; console.log(a++); console.log(++a); console.log(a); - 求整个表达式的值和变量
n的最终值:let n = 5; let r = n++ + ++n - n-- + n++; console.log(r, n); - 找出下面代码的错误并改正:
let x = 1; 5++; let y = ++(x + 1);
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | parseInt和parseFloat | 12:06 |
| 2 | 自动类型转换 | 05:38 |
| 3 | 表达式和运算符 | 07:21 |
| 4 | 运算符的分类 | 03:30 |
| 5 | 算术运算符 | 17:51 |
| 6 | 累加累减运算符 | 18:54 |
小结
parseInt/parseFloat是“提取数字”的思路,不等同于Number的整体转换。- 判断转换结果前,先看转换函数、参数类型和字符串内容。
- 自动类型转换由运算符或上下文驱动,不能脱离表达式单独猜。
- 一元
+与二元+的语义不同,遇到+先数操作数个数。 - 自增自减要同时看两件事:变量是否被修改、表达式返回旧值还是新值。
- 复杂表达式必须按求值顺序逐步跟踪变量,不能只看最终形态。
- 有副作用的表达式要求操作数可修改,实际编码中优先拆步骤、加中间输出。