Web-Dev-For-Beginners「Fun with Functions」作业全解:JavaScript 函数定义、默认参数与返回值实战
本文为 Web-Dev-For-Beginners 课程第 2 章(JavaScript 基础)第 2 课「Functions and Methods」的配套作业实战指南,完整覆盖作业文档 assignment.md 中的全部 6 个函数任务、示例测试调用与评分细则(Rubric),并给出可直接运行的完整参考答案、预期控制台输出,以及基于课程 README 中函数语法、参数、默认值、返回值与高阶函数等概念逐项对位的讲解,读完后你能独立完成从函数声明到测试验证的完整流程,并通过全部考核项。
一、作业定位:它在整个 JavaScript 基础课程中的位置
本作业属于 2-js-basics 课程目录下的第 2 课,该课程按「变量与数据类型 → 函数与方法 → 决策 → 数组与循环」四步展开。函数一课时对应课程的第二个里程碑:从「认识数据」过渡到「组织代码逻辑」。
对应课程文档(2-js-basics/2-functions-methods/README.md)的核心知识点,与作业考查点的对应关系如下:
| 课程知识点 | 对应作业任务 |
|---|---|
函数声明与调用(function name() {} + 括号调用) |
Part 1:sayHello、introduceYourself |
| 参数(Parameters)与实参(Arguments) | Part 1–4 全部涉及参数的函数 |
| 默认参数(Default Parameters) | Part 2:greetPerson;Part 4:calculateTip |
| 返回值(Return Values) | Part 3:addNumbers、createFullName;Part 4:calculateTip |
模板字符串(Template Literals,反引号 + ${}) |
Part 1 的日志输出、Part 5 的测试调用 |
| 高阶函数(函数作为参数) | Bonus Challenge 2 |
需要特别区分的一个概念(也是课程「Challenge」部分要求一句话说清的问题):函数(function)是独立的代码块,而方法(method)是挂在对象上的函数。作业末尾提示中让你按 F12 打开浏览器开发者控制台查看 console.log() 的输出——console.log 本身就是一个方法(属于 console 对象),这恰好印证了课程文档中的说明。
二、任务总览:五个部分、六个函数
作业原文要求在名为 functions-practice.js 的 JavaScript 文件中实现以下 6 个函数,分为五个部分:
| 部分 | 任务 | 函数名 | 参数 | 行为 |
|---|---|---|---|---|
| Part 1 基础函数 | 1 | sayHello |
无 | 向控制台打印 "Hello!" |
| Part 1 基础函数 | 2 | introduceYourself |
name |
打印类似 "Hi, my name is [name]" 的消息 |
| Part 2 默认参数 | 3 | greetPerson |
name(必填)、greeting(可选,默认 "Hello") |
打印类似 "[greeting], [name]!" 的消息 |
| Part 3 返回值 | 4 | addNumbers |
num1、num2 |
返回两数之和 |
| Part 3 返回值 | 5 | createFullName |
firstName、lastName |
返回合并后的完整姓名(单个字符串) |
| Part 4 综合运用 | 6 | calculateTip |
billAmount(必填)、tipPercentage(可选,默认 15) |
计算并返回小费金额 |
Part 5 则要求为以上每个函数添加测试调用,并用 console.log() 展示结果。作业给出的示例测试代码如下(原样保留自 assignment.md):
// Test your functions here
sayHello();
introduceYourself("Sarah");
greetPerson("Alex");
greetPerson("Maria", "Hi");
const sum = addNumbers(5, 3);
console.log(`The sum is: ${sum}`);
const fullName = createFullName("John", "Doe");
console.log(`Full name: ${fullName}`);
const tip = calculateTip(50);
console.log(`Tip for $50 bill: $${tip}`);
这组测试调用暗含三个考点:greetPerson 分别以 1 个和 2 个实参调用(验证默认值是否生效);addNumbers、createFullName、calculateTip 的返回值被存入 const 变量后再打印(验证「返回而非打印」的区分);calculateTip(50) 只传账单金额,验证 tipPercentage 是否按 15% 计算。
三、完整参考答案:functions-practice.js
下面给出可整体复制运行的完整参考实现,按作业的五个部分组织,并逐项标注其对应课程文档中的语法要点:
// functions-practice.js
// ========== Part 1: Basic Functions ==========
// 无参数函数:function 关键字 + 名称 + 括号 + 花括号函数体
function sayHello() {
console.log("Hello!");
}
// 单参数函数:name 是参数(形参),调用时传入的值是实参
function introduceYourself(name) {
console.log(`Hi, my name is ${name}`);
}
// ========== Part 2: Functions with Default Parameters ==========
// greeting 带默认值 "Hello":调用时省略该实参即取默认值
function greetPerson(name, greeting = "Hello") {
console.log(`${greeting}, ${name}!`);
}
// ========== Part 3: Functions that Return Values ==========
function addNumbers(num1, num2) {
return num1 + num2;
}
function createFullName(firstName, lastName) {
return `${firstName} ${lastName}`;
}
// ========== Part 4: Mix It All Together ==========
// 必填参数 + 可选默认参数 + 返回值,三合一
function calculateTip(billAmount, tipPercentage = 15) {
return billAmount * (tipPercentage / 100);
}
// ========== Part 5: Test Your Functions ==========
sayHello();
introduceYourself("Sarah");
greetPerson("Alex");
greetPerson("Maria", "Hi");
const sum = addNumbers(5, 3);
console.log(`The sum is: ${sum}`);
const fullName = createFullName("John", "Doe");
console.log(`Full name: ${fullName}`);
const tip = calculateTip(50);
console.log(`Tip for $50 bill: $${tip}`);
运行方式与预期输出
作业提示(Tip)指出,可在浏览器开发者控制台(按 F12 打开)中查看 console.log() 的输出——例如把脚本贴进控制台的 Console 面板执行即可。另外,由于脚本没有依赖 DOM,也可以直接在 Node.js 环境中运行:
node functions-practice.js
预期控制台输出为:
Hello!
Hi, my name is Sarah
Hello, Alex!
Hi, Maria!
The sum is: 8
Full name: John Doe
Tip for $50 bill: $7.5
逐行对位说明:
sayHello()→Hello!(函数体直接console.log,无返回值);introduceYourself("Sarah")→ 实参"Sarah"绑定到参数name,模板字符串插值后输出;greetPerson("Alex")→ 未提供第二个实参,greeting取默认值,输出Hello, Alex!;greetPerson("Maria", "Hi")→ 显式传入"Hi"覆盖默认值;addNumbers(5, 3)返回8,经The sum is: ${sum}打印;createFullName("John", "Doe")返回单个字符串John Doe;calculateTip(50)按默认 15% 计算:50 * (15 / 100) = 7.5。
四、逐项解析:作业背后考查的语法机制
以下解析基于课程文档 2-js-basics/2-functions-methods/README.md 的讲解脉络,帮助理解每个任务「为什么这么写」。
4.1 Part 1:函数声明与调用的最小完整形态
课程文档给出的声明语法模板是 function nameOfFunction() { /* body */ },四个组成部分分别是:
function关键字:声明意图;- 函数名:应使用能自解释意图的描述性名称(课程文档举例
cancelTimer(),且约定多词名称用 camelCasing,如calculateTotal而非calculate_total); - 圆括号
():参数列表所在(Part 1 的sayHello为空); - 花括号
{}:函数体,调用时才执行。
调用时必须带括号——写 displayGreeting 而不带 () 只会取到函数引用而不会执行函数体,这是课程文档「Function Fundamentals Check」自查清单中的问题之一。定义与调用的先后顺序不受限制,JavaScript 引擎会处理执行顺序。
4.2 Part 2:默认参数如何让函数「向前兼容」
greetPerson(name, greeting = "Hello") 对应课程文档的「Default values」小节。文档用几乎同构的例子(displayGreeting(name, salutation='Hello'))说明:默认值写法与普通变量赋值一样用等号;第一个实参缺失时取默认值,传入时则覆盖默认值。文档强调这种设计的价值在于调用者可以低成本上手(合理默认值),又保留定制能力,且旧调用方式无需修改(向后兼容)。
注意一个细节:默认参数必须放在必填参数之后。若写成 greetPerson(greeting = "Hello", name),则只传一个实参时该值会绑定给 greeting,语义立刻错乱——这正是 Rubric 中「Parameters & Default Values」项区分 Exemplary 与 Needs Improvement 的地方之一。
4.3 Part 3:返回值 vs 打印——两种截然不同的函数契约
Part 3 是作业中区分度最高的一部分。addNumbers 和 createFullName 的共同点是「计算并交还结果」,而不是「把结果显示在控制台」:
function addNumbers(num1, num2) {
return num1 + num2;
}
课程文档对此有两条关键说明,均直接决定了本部分能否得满分(Rubric 的「Return Values」项):
return立即终止函数执行,并把值交回给调用者;return之后的代码不会运行;- 没有
return的函数返回undefined,这类函数只产生副作用(如打印日志、修改 DOM)。
由此可以对照作业的任务划分:Part 1/2 的三个函数(sayHello、introduceYourself、greetPerson)是「只执行动作」型,Part 3/4 的三个函数(addNumbers、createFullName、calculateTip)是「交还数据」型。混淆两类契约的典型错误是:在 addNumbers 里写 console.log(num1 + num2) 而没有 return——此时测试代码中的 const sum = addNumbers(5, 3) 会拿到 undefined,输出变成 The sum is: undefined,正好可以通过 Part 5 的测试暴露问题。
返回值的用途也由此展开:存入变量(如 const fullName = ...)、参与表达式、传给另一个函数。返回的也可以是任意类型(字符串、数字、布尔、对象、数组),课程文档的「Return Value Types」图统计了常见返回类型分布。
4.4 Part 4:默认参数 + 返回值的综合运用
calculateTip 的作业要求是:billAmount 必填、tipPercentage 可选且默认 15、计算并返回小费金额。注意「返回」二字——它不能像 greetPerson 那样只打印。实现上需要把百分比换算为小数(tipPercentage / 100),这是任务隐含的算术细节;calculateTip(50) 应得到 7.5,与 Part 5 测试预期一致。
五、评分细则(Rubric)解读:五项考核标准逐条对照
作业文档附带的评分表完整如下,这里逐条补充「什么样算 Exemplary」的判据:
| 考核项 | Exemplary(优秀) | Adequate(合格) | Needs Improvement(需改进) |
|---|---|---|---|
| 函数创建 | 6 个函数全部正确实现,语法与命名规范 | 4–5 个正确,少量语法问题 | ≤3 个或存在严重语法错误 |
| 参数与默认值 | 必填参数、可选参数、默认值均按要求正确使用 | 参数使用正确但默认值处理有瑕疵 | 参数实现错误或缺失 |
| 返回值 | 应返回的函数正确返回值,不应返回的函数只做动作 | 大部分返回值正确,有小问题 | return 语句存在明显问题 |
| 代码质量 | 整洁、组织良好、变量名有意义、缩进规范 | 能运行但可读性/组织性一般 | 难以阅读或结构混乱 |
| 测试 | 所有函数都有测试调用且结果清晰展示 | 大部分函数测试充分 | 测试缺失或不正确 |
对照自查清单:
- 函数创建:6 个函数一个不少;命名沿用作业指定的
sayHello、greetPerson等 camelCase 名称,不要自造同义别名; - 参数与默认值:
greetPerson的第二参默认"Hello"、calculateTip的第二参默认15,且两者都能被显式实参覆盖; - 返回值:三个「返回型」函数必须用
return交出值(否则sum、fullName、tip全是undefined);三个「动作型」函数不要加return(如return console.log(...)会返回undefined,属于多余且暴露对契约的误解); - 代码质量:参考第三节的排版——分部分注释、参数命名与作业要求一致、统一缩进;
- 测试:直接沿用 Part 5 的示例调用即可覆盖全部 6 个函数,并额外验证了
greetPerson的两种调用形态与calculateTip的默认值路径。
六、Bonus Challenges 参考答案
作业末尾提供了三个选做挑战(原样继承自 assignment.md):1)为其中一个函数写箭头函数版本;2)创建一个接收函数作为参数的函数(类似课程中 setTimeout 的例子);3)为函数添加输入校验,优雅处理非法输入。对应参考实现如下,可追加到 functions-practice.js 末尾:
// Bonus 1: addNumbers 的箭头函数版本
// 单表达式箭头函数可省略花括号与 return(隐式返回)
const addNumbersArrow = (num1, num2) => num1 + num2;
console.log(addNumbersArrow(5, 3)); // 8
// Bonus 2: 高阶函数——接收「函数」作为参数(课程文档 setTimeout 同款模式)
// applyTwice 把一个函数 fn 应用两次:fn(fn(value))
function applyTwice(fn, value) {
return fn(fn(value));
}
const double = (x) => x * 2;
console.log(applyTwice(double, 3)); // 12
// Bonus 3: 输入校验——对非法输入抛出明确错误
function addNumbersSafe(num1, num2) {
const invalid =
typeof num1 !== "number" ||
typeof num2 !== "number" ||
Number.isNaN(num1) ||
Number.isNaN(num2);
if (invalid) {
throw new TypeError("Both arguments must be valid numbers");
}
return num1 + num2;
}
console.log(addNumbersSafe(2, 3)); // 5
// addNumbersSafe("2", 3); // 抛出 TypeError
三个 Bonus 分别对应课程文档「Functions as parameters for functions」「Fat arrow functions」两个小节:setTimeout(displayDone, 3000) 传递的是函数引用(注意不带括号,带了括号会立即执行并传回返回值),applyTwice 是同一模式的纯函数版本;箭头函数则与课程中 setTimeout(() => {...}, 3000) 的写法完全同构,可用于简短回调场景。
七、佐证:本仓库真实项目代码中的函数写法
为了说明这套函数技能在课程后续项目中的实际用途,仓库里已带答案的项目代码给出了两个现成的观察样本:
- 打字游戏答案 index.js 通篇采用箭头函数:如
const getRandomQuote = () => quotes[Math.floor(Math.random() * quotes.length)](无参 + 隐式返回),renderQuote接收一个参数quote并操作 DOM,messages.success = (seconds) => \...`` 则是一个带参数并返回字符串的箭头函数——正是作业 Part 3「返回模板字符串」模式的工程化放大版。 - 太空游戏答案 app.js 顶部用 IIFE(立即执行函数表达式)
(() => { ... })包裹全部逻辑,并定义了带默认参数的选择器工具const $ = (sel, ctx = document) => ctx.querySelector(sel)——ctx = document就是一个默认参数,与作业 Part 2 的greeting = "Hello"写法如出一辙。
从源码结构看,这两处代码印证了课程文档的选型建议:可复用的工具函数($、getRandomQuote)用命名函数承载、只做一次或简短的回调(事件处理、map 里的映射)用箭头函数承载。
八、验证清单:提交前逐条确认
按作业要求与 Rubric,提交前建议对照以下清单自查(每一项都可由第三节给出的预期输出直接验证):
- 文件名为
functions-practice.js,6 个函数名与作业指定完全一致; - 浏览器控制台(F12)或
node functions-practice.js的运行输出与第三节的预期输出逐行一致,尤其是Tip for $50 bill: $7.5(验证默认值 15 生效); greetPerson("Alex")与greetPerson("Maria", "Hi")的输出差异正确体现默认值覆盖逻辑;sum、fullName、tip三个变量拿到的都是真实值而非undefined(可用console.log(sum)单独抽查);- 三个动作型函数(
sayHello、introduceYourself、greetPerson)函数体内无return; - 命名采用 camelCasing,缩进统一,每个部分有清晰的分区注释;
- (选做)三个 Bonus 挑战代码追加后不影响原有测试输出。
完成以上步骤后,本作业即覆盖了 2-js-basics/2-functions-methods 一课中函数声明、参数、默认值、返回值、函数作参数、箭头函数等全部核心语法点,可直接作为进入第 3 课「Making Decisions」前的能力自测。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
