深入解析 freeCodeCamp Basic JavaScript 课程:用 return 语句返回函数值
本文围绕 freeCodeCamp 开源课程 Basic JavaScript 单元中的经典一课"Return a Value from a Function with Return"展开,结合当前仓库中该课程的原始挑战文件、区块结构与所属认证路径,逐层讲解 return 语句如何让函数把计算结果"送出去",并给出可运行的完整解题代码、自动化判定逻辑与延伸阅读路径。读完本文,你既能吃透"参数传入、返回值传出"的函数工作模型,也能直接上手完成 timesFive 挑战并通过全部测试。
本课在学习路径中的位置
本课的课程源码位于 curriculum/challenges/english/blocks/basic-javascript/56533eb9ac21ba0edf2244c2.md。挑战文件的头部元数据如下:
| 字段 | 取值 | 含义 |
|---|---|---|
id |
56533eb9ac21ba0edf2244c2 |
挑战全局唯一标识,用于结构文件与索引 |
title |
Return a Value from a Function with Return | 课程标题 |
challengeType |
1 |
课程类型标记,本类课程在正文中携带 --seed--(初始代码)与 --hints--(自动化断言)两节 |
forumTopicId |
18271 |
历史论坛讨论主题编号 |
dashedName |
return-a-value-from-a-function-with-return | 用于生成学习路径中的短横线式路径段 |
通过 dashedName 可以推断它在学习站点中对应的路径形式(仓库内相邻课程文档中可看到 /learn/.../basic-javascript/... 的完整 URL 约定)。本课归属于 JavaScript Algorithms and Data Structures 认证下的 Basic JavaScript 区块,该映射记录在 curriculum/structure/superblocks/javascript-algorithms-and-data-structures.json 中。
区块内的课程顺序定义在 curriculum/structure/blocks/basic-javascript.json 的 challengeOrder 数组中,本课位于该数组下标 50 处,前后文是典型的"由浅入深"编排:
- 下标 48:Write Reusable JavaScript with Functions(认识函数定义与调用)
- 下标 49:Passing Values to Functions with Arguments(把值作为参数传入函数)
- 下标 50:本课(Return a Value from a Function with Return)
- 下标 51:Global Scope and Functions(全局作用域)
- 下标 52、53:Local Scope and Functions、Global vs. Local Scope in Functions
- 下标 54:Understanding Undefined Value returned from a Function
- 下标 55:Assignment with a Returned Value(把返回值赋给变量)
也就是说,前一课解决"数据怎么进函数",本课解决"结果怎么从函数里出来",后一课立即把它接续成"取回返回值并赋值给变量",课程链设计一目了然。
核心知识:函数不仅要接收参数,还要"交出"返回值
课程的 # --description-- 直接点出主题:
我们可以用参数(arguments)把值传入函数,也可以用一条
return语句把值从函数里发送出去。
参数解决的是输入方向的问题:函数定义时声明的形参只是占位符,函数被调用时传入的实际值(实参)会逐一绑定到形参上。而 return 解决的是输出方向的问题——计算完成后,把结果作为函数的值交还给调用它的表达式。
在没有 return(或函数体执行完毕没有命中任何 return)的情况下,函数调用本身在 JavaScript 中会被求值为 undefined。这一点在本课之后的"Understanding Undefined Value returned from a Function"一课中还会被专门考察,说明课程设计者刻意强调"没有 return 就没有真正结果"这一易错点。
示例拆解:plusThree 到底发生了什么
课程给出的示例是把整个过程压缩成三个最小要素的经典范例:
function plusThree(num) {
return num + 3;
}
const answer = plusThree(5);
它的执行过程可以拆成四步:
- 定义阶段:用函数声明创建名为
plusThree的函数,形参为num,函数体只有一条return num + 3;。 - 求值实参:执行
plusThree(5)时,实参5被绑定到形参num。 - 计算并返回:函数体求值
num + 3,得到8,return语句立即把8作为整个调用表达式的结果交出去。 - 承接结果:调用表达式
plusThree(5)此刻已经"变成"值8,于是answer被赋值为8。
课程原文特别给出结论:answer 的值为 8;plusThree 接收针对 num 的参数,并返回等于 num + 3 的新值。这里可以提炼出一个通用认知:带返回值的函数调用,本质上就是一条会产出值的表达式,它可以被赋值、参与运算,也可以继续作为另一个函数的实参。
动手任务:实现 timesFive
课程的 # --instructions-- 要求如下:
创建一个函数
timesFive,它接收一个参数,将该参数乘以5,并返回新得到的值。
与之配套的 # --seed-- 给出了一个空白的初始代码区(即编辑器中没有任何预置代码,需要从零书写):
注意这是一个纯"从空白起步"的编写型挑战:不需要 console.log 打印,不需要修改任何全局状态,唯一要做的是定义函数并通过 return 返回乘积。
自动化判定:hints 如何验证你的答案
课程 # --hints-- 一节给出了四组断言,它们共同构成了通过标准:
| 断言 | 判定内容 | 类型检查要点 |
|---|---|---|
assert(typeof timesFive === 'function'); |
必须先存在名为 timesFive 的函数 |
用 typeof 验证声明形式(函数声明、函数表达式均可) |
assert(timesFive(5) === 25); |
传入 5 应返回 25 |
验证一般乘法路径 |
assert(timesFive(2) === 10); |
传入 2 应返回 10 |
验证中间取值 |
assert(timesFive(0) === 0); |
传入 0 应返回 0 |
验证边界输入(零值) |
注意判定样例特意覆盖了正数、小值与零三种输入。其中 timesFive(0) === 0 这条尤其能"戳穿"两类典型错误:
- 忘记
return:若只写了num * 5却没有return,函数会返回undefined,所有断言全部失败; - 在
return后继续写了不可达语句:return一旦执行,函数立即结束,其后的语句不再执行。
参考答案与逐行讲解
课程 # --solutions-- 中给出的官方参考答案:
function timesFive(num) {
return num * 5;
}
timesFive(10);
逐行分析:
- 第 1 行用函数声明定义
timesFive,形参命名为num(形参名可自由选取,与调用方的实参无关); - 第 2 行是解题核心:计算
num * 5并立刻由return返回。这里的num * 5是先求值、后返回; - 第 4 行
timesFive(10);是一次主动调用,用于在实际运行环境中让函数真正执行一次(多数断言运行器不会因为"定义了但从未调用"而报错,但调用有助于在练习环境里即时看到效果)。
要特别留意第 2 行的语义:return 右侧表达式的求值发生在返回之前。这正是仓库中后一课 Assignment with a Returned Value 所强调的原理——"等号右侧的一切会先被求值,然后才完成赋值",所以函数调用的返回值可以被直接赋值给变量:
processed = processArg(7);
同理,timesFive(5) 会在调用处"就地变成"25,进而能与 ===、赋值号等一切需要值的地方协同工作。
return 的三类典型用途(本课之后的自然延伸)
掌握了本课的最小模型后,可以把 return 的使用模式归纳为三类,它们在后续课程中都会反复出现:
- 产出计算结果供外部使用:如
plusThree、timesFive。函数的价值在于把"计算"封装起来,让调用者拿到一个值,而不是只产生屏幕输出。 - 参与表达式与赋值:函数调用本身是值,因此
const answer = plusThree(5);这类写法成立。后一课 Assignment with a Returned Value 专门训练的就是这一步。 - 提前退出并返回控制权:当函数在某分支上已得出结果或不应继续执行时,用
return立即结束。Basic JavaScript 区块中下标 80 处还有一课专门名为 "Return Early Pattern for Functions",正是对该用法的专项训练。
从代码组织角度看,return 是把函数从"只会打印的脚本片段"升级为"可被复用的计算单元"的分水岭:有了返回机制,函数才能被赋值、被组合、被更复杂的程序调度,这也是 JavaScript 函数式组合的基础。
该挑战文件本身也是一种可读的仓库资源
作为 freeCodeCamp 开源课程的一部分,每个挑战的 Markdown 都遵循稳定的分节结构:# --description--(讲解)、# --instructions--(任务)、# --hints--(断言)、# --seed--(初始代码)、# --solutions--(参考答案)。初学者在本地阅读本仓库时,可以对照 basic-javascript.json 中的课程顺序,按索引逐一攻克,用 hints 中的断言当作"自带单元测试"来检验自己的实现;也可以直接阅读 --solutions-- 学习官方推荐的写法,再对比自己的代码寻找差异。这种"题目、测试与答案同仓共存"的结构,正是练习 JavaScript 基础语法最直接的本地学习素材。
小结与自查清单
完成本课的关键可归纳为三点:函数用形参接收输入、用 return 交还输出、没有 return 的函数调用值为 undefined。提交前可用下面的清单自查:
- 是否用
function(或函数表达式)声明了名为timesFive的标识符? - 函数体是否真正书写了
return num * 5;,而不是仅仅写了num * 5;? timesFive(5)是否为25、timesFive(2)是否为10、timesFive(0)是否为0?- 是否存在
return之后还放代码导致永远不会执行的死代码?
依次对照 本课挑战文件 中的四条 hints,全部满足即视为通过。此后沿 basic-javascript.json 的顺序继续学习全局/局部作用域、无返回值函数的 undefined 以及"赋值与返回值",即可把函数这一 JavaScript 核心概念完整打通。
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