数据类型与运算
上一节用数字计算报名人数。如果成绩来自输入,拿到的可能是字符串 "86":直接加 4 会得到 "864",空输入转成数字又可能变成 0。本节围绕一条学员输入,逐步完成“识别类型 → 明确转换 → 验证结果”,为后续筛选与统计准备可靠数据。
成绩的类型问题
先在 Console 中复现这个问题:
const rawScore = "86";
console.log(rawScore + 4); // "864"
console.log(Number(rawScore) + 4); // 90两次计算使用同一份原始成绩,结果却不同。接下来要弄清输入的类型、转换规则,以及为什么转换后还要验证。各小节的代码块默认独立运行;标明接续的除外。在 Console 中重复声明同名 const 时,刷新页面后再运行。
基础类型
字符串
const studentName = "张三";
const courseName = "FastAPI Web 全栈";
const summary = `学员 ${studentName} 报名了 ${courseName}`;
console.log(summary);普通字符串使用引号,需要插值或多行内容时使用反引号模板字符串。
接着上面的代码运行:
const rawName = " 张三 ";
const cleanName = rawName.trim();
console.log(cleanName.length); // 2
console.log(courseName.includes("Web")); // true
console.log(courseName.toUpperCase());字符串不可直接修改某个字符,相关方法会返回新字符串。
数字
const score = 86;
const average = 86.5;
const absentCount = 0;JavaScript 常用的整数和小数都属于 number。
console.log(10 / 4); // 2.5
console.log(0.1 + 0.2); // 可能不是精确的 0.3浮点数存在二进制精度问题。金额、精确小数等业务需要专门方案,本基础课不展开。
NaN 表示“不是有效数字结果”,但它的类型仍是 number:
const invalidScore = Number("优秀");
console.log(invalidScore); // NaN
console.log(typeof invalidScore); // "number"
console.log(Number.isNaN(invalidScore)); // true数字还可能超出当前业务允许的范围。下面几个判断回答的是不同问题:
console.log(Number.isFinite(86.5)); // true:有限数字
console.log(Number.isFinite(Infinity)); // false:无穷大
console.log(Number.isFinite(NaN)); // false
console.log(Number.isInteger(1001)); // true:整数
console.log(Number.isInteger(86.5)); // falseNumber.isFinite() 不会先转换字符串;Number.isFinite("86") 为 false。成绩通常要求有限且在 0 到 100 之间,学员编号通常要求正整数。通过类型判断并不等于符合业务范围。
布尔值与空值
const isActive = true;
const hasPassed = false;
const score = 86;
const canGraduate = score >= 60;布尔值只有 true 和 false,不要写成字符串 "true"。比较表达式会产生布尔值。
输入中还可能出现尚未赋值或明确留空的情况:
let selectedStudent;
console.log(selectedStudent); // undefined
const adviser = null;undefined:通常表示尚未赋值或缺少结果。null:程序明确表示“这里当前没有值”。
接口字段的缺失与空值应按接口约定处理,不要把二者随意混为一谈。
历史原因导致:
console.log(typeof null); // "object"接着上面的 adviser 示例,使用严格比较判断空值:
if (adviser === null) {
console.log("暂未分配班主任");
}对象与类型判断
const student = {
id: 1,
name: "张三",
score: 86,
isActive: true,
};对象用键值对组织一条业务记录。数组、普通对象、Map 等在 typeof 结果中都可能表现为 object,具体结构还需要专门方法判断。
接着上面的 student 示例运行:
console.log(typeof student); // "object"
console.log(Array.isArray([1, 2])); // true其他常见值也可以先用 typeof 判断:
console.log(typeof "张三"); // "string"
console.log(typeof 86); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof {}); // "object"
console.log(typeof function () {}); // "function"typeof 适合初步判断,不负责识别所有具体对象类型。
类型转换与真值
字符串转换
const studentId = 1001;
const idText = String(studentId);
console.log(typeof idText); // "string"数字转换
const scoreText = "86";
const score = Number(scoreText);
console.log(score + 4); // 90Number() 要求整个字符串能解释为数字:
console.log(Number("86.5")); // 86.5
console.log(Number("86分")); // NaN
console.log(Number("")); // 0空字符串转为 0 经常不符合表单业务,所以转换前应检查是否为空。只含空格的字符串也会转为 0;应先用 trim() 去掉两端空白,保留“没有填写”和“填写了 0 分”的区别。
如果只需要从带单位的文本开头提取数字,还可以解析整数或小数:
console.log(Number.parseInt("86px", 10)); // 86
console.log(Number.parseFloat("86.5分")); // 86.5parseInt 和 parseFloat 都从开头解析,尾部无效字符可能被忽略;parseInt 建议明确写十进制基数 10。它们适合提取带单位文本中的数字,不适合验证整段成绩输入。验证成绩时使用 Number() 转换完整字符串,再检查有限性和范围。
布尔转换与真值
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean("yes")); // true
console.log(Boolean("")); // false
console.log(Boolean("false")); // true字符串 "false" 仍然是真值,因为它不是空字符串。
在条件判断中,下列常见值会被当作 false:
false
0
""(空字符串)
null
undefined
NaN数组 [] 和对象 {} 都是真值,即使它们没有元素或属性。
const students = [];
if (students.length === 0) {
console.log("暂无学员");
}不要写 if (!students) 判断空数组。
运算与条件
算术与比较
const total = 80 + 90;
const difference = 90 - 80;
const product = 3 * 20;
const average = total / 2;
const remainder = 7 % 2;
const power = 2 ** 3;+ 同时用于数字相加和字符串拼接:
console.log(10 + 5); // 15
console.log("10" + 5); // "105"表单输入通常得到字符串,参与计算前需要明确转换。
比较表达式会产生布尔值,可用来检查成绩和状态:
console.log(86 > 60);
console.log(86 >= 86);
console.log(86 < 100);
console.log(86 !== 60);默认使用严格相等:
console.log(1 === "1"); // false
console.log(1 == "1"); // true,不推荐依赖隐式转换===:值与类型都相等。!==:值或类型不相等。
基础项目避免 == 和 !=,减少隐式转换带来的意外。
逻辑与短路
const score = 86;
const isActive = true;
const canGraduate = score >= 60 && isActive;
const needsAttention = score < 60 || !isActive;&&:并且。||:或者。!:取反。
它们返回的不一定总是布尔值:
const displayName = "" || "未命名";
console.log(displayName); // "未命名"需要真正布尔结果时,使用比较表达式或 Boolean() 明确转换。
逻辑运算从左向右求值:&& 遇到假值后不再计算右侧,|| 遇到真值后不再计算右侧。这称为短路求值。
const studentName = null;
const hasValidName =
typeof studentName === "string" && studentName.trim().length >= 2;
console.log(hasValidName); // false,不会执行 null.trim()左侧先确认是字符串,右侧才调用字符串方法。把顺序倒过来就失去了保护作用。
const inputName = "张三";
const displayName = inputName || "未命名";
console.log(displayName); // "张三",不需要使用右侧默认值不要把每次都必须执行的操作放在短路表达式的右侧,例如计数或重要日志,否则它可能被跳过。
空值合并与优先级
const remark = null;
const displayRemark = remark ?? "暂无备注";?? 只在左侧是 null 或 undefined 时使用右侧值;|| 还会把 0、空字符串等假值当作缺失。
const score = 0;
console.log(score || 60); // 60,可能错误
console.log(score ?? 60); // 0乘除通常先于加减,比较通常先于逻辑组合,&& 先于 ||。比起背完整优先级表,更重要的是用括号写清业务条件:
console.log((80 + 90) / 2); // 85,先求总分再求平均分
console.log(80 + 90 / 2); // 125,含义已经不同
const score = 86;
const status = "pending";
const canJoin =
(status === "active" || status === "pending") && score >= 60;
console.log(canJoin); // true这里要求“状态为正常或待审核”并且“成绩合格”。涉及多个条件时,先用自然语言说明规则,再加括号分组。?? 与 &&、|| 混用时必须用括号明确分组。
学员输入校验
假设表单已经提供一条学员记录:name 和 score 都是字符串,id 是数字字符串,status 是状态字符串,remark 可能为 null。本节只校验成绩是否在 0 到 100 之间;编号暂时只做转换,不判定它是否为有效学员编号。
const rawStudent = {
id: "1001",
name: " 张三 ",
score: "86.5",
status: "active",
remark: null,
};
const cleanName = rawStudent.name.trim();
const studentId = Number(rawStudent.id);
const scoreText = rawStudent.score.trim();
const score = Number(scoreText);
const isActive = rawStudent.status === "active";
const remark = rawStudent.remark ?? "暂无备注";
const isValidScore =
scoreText !== "" && Number.isFinite(score) && score >= 0 && score <= 100;
console.table([
{
studentId,
cleanName,
score,
isActive,
remark,
isValidScore,
},
]);输出的姓名是“张三”,编号是数字 1001,成绩是数字 86.5,成绩验证结果为 true。验证先区分是否填写,再确认转换结果及业务范围。即使成绩转换后显示为 0 或 NaN,也要以 isValidScore 为准;验证不通过的成绩不能进入后续等级判断或统计。
练习与验收
每次只修改 rawStudent.score,先预测,再查看 isValidScore:
| 输入 | 验证结果 | 原因 |
|---|---|---|
"0"、"100" | true | 成绩上下边界都有效 |
""、" " | false | 未填写有效内容 |
"86分" | false | 不能整体转换为数字 |
"-1"、"101" | false | 超出成绩范围 |
再说明为什么 score || 60 不适合给成绩提供默认值。下一节将使用这些布尔判断,决定输出哪种成绩等级。
小结
- 常用基础类型包括字符串、数字、布尔值、
undefined、null和对象。 - 表单与接口数据进入计算前要明确转换和验证。
- 默认使用
===与!==,避免依赖宽松比较的隐式转换。 - 空数组和空对象都是真值,应检查长度或属性。
??只把null和undefined当作缺失值。&&、||会短路;先判断类型,再执行依赖该类型的操作。