☰
freeCodeCamp 基础 JavaScript 课程解析:用函数(Functions)编写可复用代码
2026/11/3 3:29:40 网站建设 项目流程

freeCodeCamp 基础 JavaScript 课程解析:用函数(Functions)编写可复用代码

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

在 freeCodeCamp 的 JavaScript 算法与数据结构课程的Basic JavaScript板块中,"Write Reusable JavaScript with Functions" 这一课首次系统性地引入函数概念,教你把代码拆分为可复用、可随时调用的小单元。通过本课学习,你不仅能掌握函数定义与调用的基础语法,还能理解 freeCodeCamp 在线课堂如何通过自动测试逐条校验你的代码,为后续学习传参、返回值与作用域奠定基础。

一、本节挑战在课程中的位置

本课对应的挑战源文件位于仓库curriculum/challenges/english/blocks/basic-javascript/56bbb991ad1ed5201cd392cf.md,文件名中嵌入的56bbb991ad1ed5201cd392cf是它在 freeCodeCamp 课程体系中的唯一挑战 ID。

从 Basic JavaScript 板块结构定义 可以看到,该板块(helpCategory 为 JavaScript,共 113 道挑战)的编排逻辑:

序号挑战标题主题
47Shopping List购物清单(数组综合练习)
48Write Reusable JavaScript with Functions函数入门(本课)
49Passing Values to Functions with Arguments参数与实参
50Return a Value from a Function with Returnreturn 返回值
51Global Scope and Functions全局作用域
52Local Scope and Functions局部作用域
53Global vs. Local Scope in Functions全局与局部作用域对比

也就是说,本课是 Basic JavaScript 板块中进入函数世界的起点:它先让学习者认识"函数可以把一段代码打包成可复用单元",随后的课程才逐步加入参数、返回值与作用域规则。理解了这一点,就能明确本课的目标边界——只聚焦于"定义 + 调用"两个最基础动作。

二、核心概念:什么是函数

原文档给出的定义非常精炼:

In JavaScript, we can divide up our code into reusable parts calledfunctions.

即:函数(function)是把一段代码划分出来的可复用部分。当同一段逻辑需要在多处出现时,不必复制粘贴整段代码,而是把它放进函数里,需要时调用即可。

函数声明(function declaration)的基本形态如下:

function functionName() { console.log("Hello World"); }

逐段拆解这段语法:

  • function:声明函数的关键字;
  • functionName:函数名,遵循标识符命名规则,应能表达函数用途;
  • 一对圆括号():函数定义阶段的参数占位位置。本课示例不含参数,圆括号为空;
  • 一对花括号{}:函数体,即每次调用函数时都会执行的全部语句。

原文档强调了一个重要事实:花括号之间的所有代码,每次调用函数时都会被完整执行一遍。因此函数天然具备"复用逻辑、统一行为"的价值——只要修改函数体一处,所有调用点都会同步生效。

三、调用函数:名称加圆括号

定义函数只是"打包代码",真正执行还需要调用(call)或调用(invoke)它。调用方式是用函数名加一对圆括号:

functionName();

执行上述语句后,控制台(dev console)会输出一次Hello World。

这里有几个初学者容易混淆的点,值得强调:

  1. 定义与调用是两步动作。只写function functionName() { ... }不会触发函数体执行;必须出现functionName();才会真正运行。
  2. 圆括号是"调用标记"。函数名后面紧跟()表示要执行它;如果不加圆括号而只写functionName,在 JavaScript 中拿到的是对函数本身的引用(后续学习回调函数时常用),函数体并不会执行。
  3. 可以反复调用。functionName(); functionName();会连续输出两次Hello World,这正是"可复用"最直观的体现。

四、本课任务:创建并调用 reusableFunction

--instructions--部分给出了两道明确指令:

  1. 创建一个名为reusableFunction的函数,向控制台打印字符串Hi World;
  2. 调用该函数。

挑战的初始代码(--seed-contents--)是一个空白的编辑器,需要你从零写起。--solutions--部分给出了官方参考答案:

function reusableFunction() { console.log("Hi World"); } reusableFunction();

对照参考答案可以确认两个要点:

  • 函数体的输出内容必须精确匹配Hi World(大小写、空格都不能错),因为自动判题会做严格字符串比对;
  • 函数定义之后必须单独调用一次reusableFunction();,两条指令缺一不可。

五、自动判题机制:hints 是如何验证你通过的

freeCodeCamp 的挑战都通过 Markdown 中的--hints--段落声明自动测试。本课共有三条断言,逐条对应前面的指令要求。

1. reusableFunction 必须是一个函数

assert(typeof reusableFunction === 'function');

通过typeof运算符确认reusableFunction的类型是function。只要定义动作缺失或定义成了普通变量,这条就会失败。

2. 调用后必须输出 Hi World

assert(testConsole());

这条依赖文档中--before-each--段落注入的辅助函数testConsole。它在每次测试执行前会:

  • 缓存原始console与原生console.log;
  • 临时覆写console.log,当检测到消息精确等于Hi World时置hiWorldWasLogged = true;
  • 在覆写期间主动调用一次reusableFunction();
  • 最后恢复原生console.log并返回hiWorldWasLogged。

因此这条断言验证的不只是"函数被定义",而是"调用后确实向控制台输出了正确字符串"。

3. 定义之后必须真的调用过

const functionStr = reusableFunction && __helpers.removeWhiteSpace(reusableFunction.toString()); const codeWithoutFunction = __helpers.removeWhiteSpace(__helpers.removeJSComments(code)).replace(/reusableFunction\(\)\{/g, ''); assert(/reusableFunction\(\)/.test(codeWithoutFunction));

这条测试先剔除代码中的注释与空白字符(__helpers.removeWhiteSpace、__helpers.removeJSComments),再把"定义语句本身的reusableFunction(){}"模式移除,最后用正则/reusableFunction\(\)/检查源码中确实存在独立的调用表达式。这样的写法能有效避免"只定义、没调用"或"通过注释里的函数名蒙混过关"的取巧情况。

六、挑战源文件的结构化格式

本课文件(.md)本身并不是给人阅读的普通文章,而是 freeCodeCamp 课程引擎可以解析的结构化源数据。文件开头由---包裹的 frontmatter 声明了元信息:

id: 56bbb991ad1ed5201cd392cf # 挑战唯一 ID,课程顺序引用依赖它 title: Write Reusable JavaScript with Functions # 挑战标题 challengeType: 1 # 挑战类型标识 forumTopicId: 18378 # 关联论坛讨论主题 ID dashedName: write-reusable-javascript-with-functions # URL 友好的短横线命名

正文则通过若干语义化区块组织内容,本课用到了:

区块作用
# --description--面向学习者的概念讲解(本课的函数介绍与示例)
# --instructions--可操作的任务清单
# --before-each--每次测试运行前注入的辅助脚本
# --hints--自动判定的断言清单
# --seed-contents--初始种子代码(本课为空,需从零编写)
# --solutions--官方参考答案,用于示例展示与测试对照

如果对这套格式本身感兴趣,可以进一步查看仓库中的挑战结构与校验相关工具,例如curriculum/schema/challenge-schema.js(挑战结构约束)与 Basic JavaScript 板块结构定义 basic-javascript.json。而本课源文件同目录下还存放着整个 Basic JavaScript 板块的全部 100 余个挑战,例如前一课的 Shopping List 与紧随其后的 Passing Values to Functions with Arguments。

七、学完本课后:下一步与自学建议

在课程中的衔接

本课只是函数的"第一课"。紧接着的下一个挑战 Passing Values to Functions with Arguments 就会引入**参数(parameters)与实参(arguments)**的概念:参数是函数定义时占位用的变量,实参是调用时真正传入的值。例如:

function testFun(param1, param2) { console.log(param1, param2); } testFun("Hello", "World");

再往后,课程还会依次讲解return返回值、全局/局部作用域,以及"undefined 返回值"等进阶主题。因此建议按板块顺序逐课推进,确保函数体系的知识环环相扣。

自学验证建议

在本地浏览器控制台或 Node.js 环境中,可以自行验证本课知识:

function reusableFunction() { console.log("Hi World"); } reusableFunction(); // 控制台输出: Hi World reusableFunction(); // 再次调用,再次输出: Hi World

尝试对比以下两种情况,能帮助你加深对"定义"与"调用"区别的理解:

// 只定义、不调用:没有任何控制台输出 function demo() { console.log("never shown"); } // 引用而不调用:同样没有任何输出,demo 是函数对象本身 demo; // 调用:圆括号触发执行 demo();

结语

"Write Reusable JavaScript with Functions" 虽然只覆盖了函数最基础的"定义 + 调用"语法,但它奠定了整个函数体系的学习起点。通过本文对挑战源文件、板块排序与自动判题逻辑的逐层拆解,你可以看到 freeCodeCamp 如何用结构化的 Markdown 源数据驱动一套完整的在线练习闭环——而理解这套机制,无论对你完成当前挑战,还是日后为开源社区贡献课程内容,都大有裨益。

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询