news 2026/9/7 8:58:57

Making Decisions 实战:在 Web-Dev-For-Beginners 中构建学生成绩处理器(Student Grade Processor)完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Making Decisions 实战:在 Web-Dev-For-Beginners 中构建学生成绩处理器(Student Grade Processor)完整指南

Making Decisions 实战:在 Web-Dev-For-Beginners 中构建学生成绩处理器(Student Grade Processor)完整指南

【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners

本文围绕 Web-Dev-For-Beginners 课程"JavaScript Basics"模块第 3 课《Making Decisions》的课后作业 assignment.md 展开:你将基于if...else分支、typeof类型判断、比较运算符与逻辑运算符,完成一个处理两套不同评分体系的学生成绩筛选程序。读完后你将掌握如何在动态类型的 JavaScript 中编写可靠的分支逻辑,并学会用多组测试数据验证、以及用校验、统计、分数换算三个方向对程序做实战扩展。

任务背景:两套评分体系的合并处理问题

作业文档给出了一个贴近真实业务的问题设定:你所在学校最近与另一所学校合并,现在需要处理来自两套完全不同的评分体系的学生成绩,并判断哪些学生通过(passing)。这正是练习条件逻辑(conditional logic)的典型场景。

作业的学习目标是(引自 assignment.md):

In this assignment, you'll practice the decision-making concepts from this lesson by building a program that processes student grades from different grading systems. You'll useif...elsestatements, comparison operators, and logical operators to determine which students pass their courses.

两套评分体系的规则拆解

在写任何代码之前,先把两套体系的判定规则拆清楚。这是整个程序判定逻辑的唯一事实来源:

维度第一套体系(Numeric 数字制)第二套体系(Letter 字母制)
成绩形态数字 1–5字符串:AA-BB-CC-
及格线3 及以上(3、4、5)列出的全部字母成绩均及格
不及格情形小于 3(1 或 2)该体系不包含DF等不及格字母

两条规则对分支逻辑的直接影响:

  • 数字制只需要一个"范围比较":grade >= 3
  • 字母制没有大小顺序可比较,只能做"白名单成员判断":检查该字符串是否属于六个有效字母成绩之一,这正是作业指定用逻辑运算符||串联多个等值判断的原因。

任务定义:allStudents 样本数据与期望输出

作业给定如下混合数组allStudents,要求构造新数组studentsWhoPass,收集其中所有及格的成绩:

let allStudents = [ 'A', // Letter grade - passing 'B-', // Letter grade - passing 1, // Numeric grade - failing 4, // Numeric grade - passing 5, // Numeric grade - passing 2 // Numeric grade - failing ]; let studentsWhoPass = [];

逐个元素的判定过程如下:

元素typeof结果适用规则判定
'A''string'字母制白名单命中及格
'B-''string'字母制白名单命中及格
1'number'1 >= 3为 false不及格
4'number'4 >= 3为 true及格
5'number'5 >= 3为 true及格
2'number'2 >= 3为 false不及格

期望输出为['A', 'B-', 4, 5]。注意结果的顺序与输入顺序一致——因为studentsWhoPass是按遍历顺序逐个push进去的,这也为后续测试验证提供了确定性基准。

参考实现:完整可运行的解决方案

作业给出的 Step-by-Step 方法是四步:1)设一个循环遍历每个成绩;2)检查成绩类型(数字还是字符串?);3)按对应体系的规则判定(数字看>= 3,字符串看是否属于有效及格字母);4)把及格成绩 push 进结果数组。下面是一份严格按这四步实现的参考代码:

let allStudents = [ 'A', // Letter grade - passing 'B-', // Letter grade - passing 1, // Numeric grade - failing 4, // Numeric grade - passing 5, // Numeric grade - passing 2 // Numeric grade - failing ]; let studentsWhoPass = []; // 步骤 1:循环遍历 allStudents 中的每个成绩 for (const grade of allStudents) { // 步骤 2:先判断类型——是数字成绩还是字母成绩? if (typeof grade === 'number') { // 步骤 3a:数字体系——>= 3 及格 if (grade >= 3) { // 步骤 4:把及格成绩加入结果数组 studentsWhoPass.push(grade); } // 数字且 < 3:不及格,什么都不做 } else if (typeof grade === 'string') { // 步骤 3b:字母体系——逐个核对六个有效及格字母 if (grade === 'A' || grade === 'A-' || grade === 'B' || grade === 'B-' || grade === 'C' || grade === 'C-') { studentsWhoPass.push(grade); } // 字符串但不在白名单内(如 'D'):视为无效/不及格 } // 其他类型(undefined、null、boolean 等):默认不通过 } console.log(studentsWhoPass); // ['A', 'B-', 4, 5]

实现中有两个值得注意的设计决策:

类型分派(type dispatch)放在最外层。因为 JavaScript 是动态类型语言,同一个数组里可以合法地混放字符串和数字(这正是本任务的核心难点),所以"先问类型、再选规则"必须发生在任何规则判断之前。反过来,如果你先写grade >= 3,字符串'A'参与比较时行为将完全不可预期。

字母判断用===而非==配套课程 README 明确指出:严格相等===会同时检查值和类型(5 === '5'返回false),而宽松相等==会先做隐式类型转换,"Always use===and!==for equality checks unless you specifically need type conversion"。在本任务中字符串与字符串比较,用===是最稳妥的写法。

作业点名的五项关键技术工具

assignment 的 "Helpful Code Techniques" 一节明确列出了本课要练习的五个技术点。结合上面参考实现,它们各自承担的职责如下:

技术点作业原话要点在本任务中的职责
typeof运算符typeof grade === 'number'判断是否数字成绩最外层分派:决定走数字规则分支还是字母规则分支
比较运算符>=比较数字成绩数字体系的及格线判定grade >= 3
逻辑运算符||检查多个字母成绩条件串联六个字母的白名单成员判断
if...else语句处理不同的评分体系两套规则互斥执行,保证每个成绩只走一条路径
数组方法.push()把及格成绩加入新数组结果收集器

其中||(Logical OR)值得再展开一句:作业要求用它检查多个字母条件,从源码行为上看它做短路求值——六个等值判断中只要有一个为true,后面的表达式就不再求值,直接得到true。配套课程在讲&&时特别提到了这一特性("Performance tip: JavaScript uses 'short-circuit evaluation'"),||同理。把最可能命中的条件放在链条前端,在性能敏感场景下是惯例写法;本任务六个分支概率接近,按字母顺序排列即可。

测试你的解决方案

assignment 的 "Testing Your Solution" 一节要求用不同组合的成绩验证代码,原文给出的两组测试数据是:

// Test with different grade combinations let testGrades1 = ['A-', 3, 'C', 1, 'B']; let testGrades2 = [5, 'A', 2, 'C-', 4]; // Your solution should work with any combination of valid grades

按作业定义的两套规则推导,这两组数据的期望输出分别是:

测试输入逐元素判定期望的studentsWhoPass
['A-', 3, 'C', 1, 'B']'A-'通过;3 >= 3通过;'C'通过;1 < 3失败;'B'通过['A-', 3, 'C', 'B']
[5, 'A', 2, 'C-', 4]5通过;'A'通过;2 < 3失败;'C-'通过;4通过[5, 'A', 'C-', 4]

验证方法很简单:把循环逻辑封装成可复用的形式(或直接在每次运行前重置studentsWhoPass = []),用console.log/console.table输出结果与期望值比对。除了这两组,提交前还应考虑 assignment "Submission Guidelines" 提示的边界场景,例如空数组(应得到[]而不是报错)和意外的数据类型(参考实现中else if (typeof grade === 'string')之后的隐式兜底分支就是为这类输入准备的)。

附加挑战:校验、统计与成绩换算

assignment 在基础任务之外给出了三个扩展方向(Bonus Challenges),逐个说明实现思路:

1)加入校验(Add validation)。检测非法成绩,例如负数字或不在白名单里的字母。核心做法是在两套规则内部再各加一层合法性判断:数字制要求grade >= 1 && grade <= 5,字母制则检查grade是否属于六个有效字母,两者都不满足时console.log出告警而不是静默丢弃。

2)统计通过/失败人数(Count statistics)。借助条件表达式把判定结果收敛为布尔值,再累加计数。这里可以顺带练习课程中的三元运算符:

let passCount = 0; let failCount = 0; for (const grade of allStudents) { // 三元运算符:数字制看 >= 3,字母制看白名单 const isPassing = (typeof grade === 'number') ? grade >= 3 : (grade === 'A' || grade === 'A-' || grade === 'B' || grade === 'B-' || grade === 'C' || grade === 'C-'); if (isPassing) { passCount++; } else { failCount++; } } console.log(`Passing: ${passCount}, Failing: ${failCount}`); // 对 allStudents:Passing: 4, Failing: 2

3)成绩换算(Grade conversion)。把所有成绩统一到数字制(A=5B=4C=3等)。用switch实现还能顺带练习课程中讲的多分支结构,并且演示了break的用途——多个case连续叠放、共用一个出口(fall-through),正是"忘记 break 会发生什么"这个问题的反面教材:

function convertToNumber(grade) { if (typeof grade === 'number') { return grade; // 已经是数字制,原样返回 } switch (grade) { case 'A': case 'A-': return 5; case 'B': case 'B-': return 4; case 'C': case 'C-': return 3; default: return null; // 无法识别的字母成绩 } } // convertToNumber('B-') -> 4 // convertToNumber(4) -> 4 // convertToNumber('D') -> null

注意switch中每个分支用return而非break提前退出,避免了 fall-through 带来的连锁执行——课程 README 强调switch适用于"一个变量对比多个离散值"的场景,而范围判断(如>= 3)仍应使用if...else,本任务的字母白名单恰好落在前者。

评分标准(Rubric)与提交清单

assignment 附带的评分表从四个维度、每维 1–4 分评估作业,完整继承如下:

维度优秀 (4)熟练 (3)发展中 (2)起步 (1)
功能性程序正确识别两套体系中的全部及格成绩程序基本可用,存在小问题或边界瑕疵程序部分可用但有逻辑错误程序存在严重错误或无法运行
代码结构代码整洁、组织良好,if...else逻辑得当结构良好,条件语句使用恰当结构尚可但有一定组织问题结构差,逻辑难以跟随
概念运用有效运用比较运算符、逻辑运算符与条件语句良好运用课程概念,存在小缺口运用了部分课程概念但缺少关键要素课程概念运用有限
问题解决对问题理解清晰,解法思路优雅解题思路良好,逻辑扎实解决问题能力尚可,略有混乱思路不清,未体现出理解

提交前的四项检查清单(引自 assignment "Submission Guidelines"):

  1. 用题目给出的示例充分测试代码;
  2. 为逻辑(尤其是条件语句)添加注释
  3. 核对输出与期望结果['A', 'B-', 4, 5]一致;
  4. 考虑边界情况,如空数组、意外数据类型。

作业最后还附了一条 Pro Tip:Start simple! 先让基础功能跑起来,再叠加更复杂的功能——目标是运用本课学到的工具练习决策逻辑,而不是追求炫技。

现实印证:同一决策模式在仓库真实项目中的应用

本作业的分支模式并非孤立练习。仓库中的 memory-game/components/MemoryGame.jsx(Next.js 记忆翻牌游戏组件)里可以看到与作业完全同构的决策代码:

  • 范围 + 整除的复合校验:网格尺寸输入处理中用if (2 <= size && size <= 10 && (size % 2 === 0))同时约束范围与奇偶性,不满足时进入else分支给出错误提示(见 MemoryGame.jsx#L26-L34)——这正是作业 Bonus 1"加校验"思路的实战版;
  • 多分支状态机handleClick依据disabledwon守卫条件和flipped.length的取值(0 或 1)走不同分支,逻辑骨架与作业的"类型分派 → 规则判定"一致(见 MemoryGame.jsx#L74-L92);
  • 短路求值:胜利判定if (selectedPairs.length === array.length && array.length > 0)中,&&左侧为false(空数组)时右侧根本不会被求值,避免了空数组场景下的无谓比较(见 MemoryGame.jsx#L97-L101);
  • 三元表达式:渲染层用{isFlipped(card.id) ? card.number : "?"}{won ? "You Won!" : ""}做行内二选一(见 MemoryGame.jsx#L142),对应课程中"简单条件赋值可用三元替代 if...else"的写法。

从源码结构看,作业里"先判类型/状态、再按规则分支"的写法与真实项目中的输入校验、状态守卫、UI 条件渲染一脉相承——完成这份作业等于提前接触了后续项目(如本仓库的 memory-game 与 quiz-app)中会反复出现的决策骨架。

相关学习资源

  • 本课完整讲义(布尔、比较运算符表、if/if...else/switch、逻辑运算符、三元表达式与短路求值):2-js-basics/3-making-decisions/README.md
  • 本作业原文:2-js-basics/3-making-decisions/assignment.md
  • 下一课《Arrays and Loops》(作业中.push()与循环遍历的延伸):2-js-basics/4-arrays-loops/README.md
  • JavaScript 基础模块总览(共 4 课):2-js-basics/README.md
  • 真实决策逻辑参考实现:memory-game/components/MemoryGame.jsx

【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 8:56:41

嵌入式虚拟仿真平台:点灯程序入门到工具链实战

很多想入门嵌入式的同学&#xff0c;第一道坎通常不是 C 语言&#xff0c;而是“手上没有板子”。买一块 STM32 开发板&#xff0c;快递还没到&#xff0c;教程已经刷完了十集&#xff1b;板子到手&#xff0c;装驱动、接线、搞下载器&#xff0c;折腾一晚上&#xff0c;灯没亮…

作者头像 李华
网站建设 2026/9/7 8:56:07

AD9910驱动包深度解析:RAM模式与DRG模式调幅频实战

简介&#xff1a;面向STM32F103与Keil5开发者的AD9910 DDS驱动资源包&#xff0c;聚焦调幅调频、RAM模式与DRG模式等应用&#xff0c;解决从底层寄存器配置到上层波形生成的实际问题。压缩包约6.37MB&#xff0c;共221个文件&#xff0c;以C源文件、头文件及工程配置文件为主&a…

作者头像 李华
网站建设 2026/9/7 8:55:47

Adobe Reader离线安装包全攻略:下载、静默安装与部署

简介&#xff1a;Adobe Reader是由Adobe官方出品的专业PDF阅读与轻量批注工具&#xff0c;适用于需要跨平台查看、审阅和打印PDF文档的个人用户与办公人员&#xff0c;尤其适合对版式保真度和交互式表单有要求的场景。压缩包共274个文件&#xff0c;大小约102.16MB&#xff0c;…

作者头像 李华
网站建设 2026/9/7 8:55:12

用智能体在Xcode中生成SwiftUI UI原型的工作流

在实际项目中&#xff0c;UI 原型承担的任务很明确&#xff1a;在写正式业务代码之前&#xff0c;先把页面长什么样、状态怎么切换、交互往哪里走说清楚。过去做 UI 原型通常用 Axure 或 Figma&#xff0c;先画图再让开发翻译成代码&#xff1b;现在可以换一种方式&#xff1a;…

作者头像 李华