首页
/ freeCodeCamp JavaScript 基础:用 for 循环遍历数组(Iterate Through an Array with a For Loop)深度解析

freeCodeCamp JavaScript 基础:用 for 循环遍历数组(Iterate Through an Array with a For Loop)深度解析

2026-09-07 18:09:38作者:宗隆裙

本篇文章围绕 freeCodeCamp 开源课程中 "Basic JavaScript"(JavaScript 基础)模块的一课——Iterate Through an Array with a For Loop 展开。通过本课讲解与仓库源码佐证,你将彻底掌握 for 循环遍历数组的完整套路:零基索引(zero-based indexing)、arr.length 边界条件、累加器(accumulator)模式,以及 freeCodeCamp 如何通过断言(assertion)自动判定你的答案是否正确。学完即可在 freeCodeCamp 学习平台及任何 JavaScript 环境中独立完成同类数组求和、统计、筛选任务。

一、挑战定位:它在 Basic JavaScript 课程中的位置

本挑战的题目全称是 "Iterate Through an Array with a For Loop"(用 for 循环遍历数组),挑战类型为 challengeType: 1(即经典算法/编码挑战),其课程块为 basic-javascript。在 curriculum/structure/blocks/basic-javascript.json 中,可以清楚看到它的前后编排(约 L402-L405):前面依次是 "Iterate with JavaScript For Loops"(for 循环入门)、"Iterate Odd Numbers With a For Loop"(用 for 循环迭代奇数)、"Count Backwards With a For Loop"(用 for 循环倒数),本挑战紧接其后,再往后是 "Nesting For Loops"(for 循环嵌套)、"Iterate with JavaScript Do...While Loops"(do...while 循环)与 "Replace Loops using Recursion"(用递归替代循环)。

也就是说,在课程设计者的意图里,学习者应当已经掌握 for 循环的三段式基本语法,本挑战负责引入一个重要、高频的新场景:把数组的每个元素依次读出来处理。这也是后续所有数组遍历类挑战、乃至真实前端项目中处理数据列表的基础功。

二、核心概念一:数组是零基索引的

本挑战说明文字(--description--)第一句话就点明要旨:在 JavaScript 中遍历数组内容是一个常见任务,而 for 循环是完成它的方式之一。它的示例代码把数组 arr 的每个元素输出到控制台:

const arr = [10, 9, 8, 7, 6];

for (let i = 0; i < arr.length; i++) {
   console.log(arr[i]);
}

运行这段代码,控制台会依次打印 109876。为什么能完整覆盖 5 个元素?关键在于数组下标从 0 开始计数(zero-based indexing)

  • 第一个元素是 arr[0],值是 10
  • 最后一个元素是 arr[4],值是 6
  • 数组最后一个元素的下标恒为 length - 1,也就是 5 - 1 = 4

因此循环的边界条件写成 i < arr.length 而不是 i <= arr.length。若误写成 <=,最后一次会尝试读取 arr[5],得到 undefined——这正是新手最容易踩的"差一错误(off-by-one error)"。

逐步推演循环的执行轨迹

仍以上面的 5 元素数组为例,课程说明给出了非常精确的执行推演:

  1. 初始化:i = 0
  2. 条件检查 0 < 5true,读取并输出 arr[0],即 10;执行 i++i 变为 1
  3. ……依次类推,当 i 到达 4 时,4 < 5 仍为真,输出 arr[4],即 6,这是最后一次迭代;
  4. 随后 i++i 增加到 5
  5. 再次检查条件 5 < 5,结果为 false循环终止

课程描述中特别强调"本案例中最后一次迭代是 i === 4,即 i 等于 arr.length - 1,向控制台输出 6。然后 i 增长到 5,因为 i < arr.lengthfalse,循环结束"——这正是 for 循环执行顺序(初始化 → 条件 → 循环体 → 更新表达式 → 再条件)的完整写照。

为什么循环体用 arr[i] 而不直接写死下标

因为 i 每次迭代递增,arr[i] 会依次指向第 1、2、3……个元素。这样一来,即使把数组换成 [1, 2, 3, 4, 5, 6, 7] 甚至 1000 个元素的数组,同一段循环代码无需任何修改就能完整遍历。这也是用循环处理集合数据相对手写一行行 console.log(arr[0])console.log(arr[1])…… 的本质优势:代码量不随数据规模增长

三、回顾基础:for 循环的三段式结构

本挑战的前置课程 Iterate with JavaScript For Loops 已对语法做过定义:for 循环由三个被分号分隔的可选表达式组成,形如 for (a; b; c)

位置 名称 何时执行 典型用途
a 初始化语句(initialization) 循环开始前仅执行一次 定义并设置循环变量,如 let i = 0
b 条件语句(condition) 每次迭代开始前都会被求值 只要为 true 就继续;一开头就为 false 则循环体一次都不执行
c 最终表达式(final expression) 每次迭代结束、下一次条件检查之前 递增或递减计数器,如 i++i += 2i -= 2

值得注意的是,这三个表达式都是可选的(这也是面试与课程反复考察的语法细节)。而遍历数组时,三者的"黄金搭配"就是:

for (let i = 0; i < arr.length; i++) {
  // 使用 arr[i]
}

即:从第一个元素开始、以数组长度为上界、每次步进一个下标。若想步进为 2,只需把最终表达式改为 i += 2,正如姊妹挑战 Iterate Odd Numbers With a For Loop 所示;若想从尾部向头部遍历,则把初始化和条件反转为 for (let i = arr.length - 1; i >= 0; i--)

四、实战任务:用累加器求数组元素之和

学完概念后,本挑战的 --instructions--(任务说明)要求你动手实现一个数组求和累加器

声明一个变量 total 并初始化为 0。使用一个 for 循环把 myArr 数组中的每个元素的值累加到 total 上。

同时,--seed-- 给出了初始代码骨架:

// Setup
const myArr = [2, 3, 4, 5, 6];

// Only change code below this line

这里的 myArr = [2, 3, 4, 5, 6] 是一个长度 5、首项为 2 的连续整数数组。种子代码刻意保留两行注释:Setup 段落是题目给定的,学习者只能在 // Only change code below this line 之下补充代码——这也是 freeCodeCamp 所有编码挑战的统一约定,保证判题时测试代码能可靠地基于固定结构运行。

参考实现(--solutions--)

仓库中本挑战自带的官方解法如下:

const myArr = [2, 3, 4, 5, 6];
let total = 0;

for (let i = 0; i < myArr.length; i++) {
  total += myArr[i];
}

拆开来看,这个解法包含三个关键动作:

  1. let total = 0;:先声明一个可重新赋值的 let 变量并清零。累加器必须用 let(或 var)而不是 const,因为每次迭代都要改写它的值;
  2. for (let i = 0; i < myArr.length; i++):标准遍历头,保证 i 覆盖下标 04
  3. total += myArr[i];:复合赋值运算符 +=,等价于 total = total + myArr[i];,把当前元素加进总和。

手算验证执行结果

初始化后 total = 0,随后 5 次迭代依次累加:

迭代次数 i myArr[i] 执行后 total
1 0 2 2
2 1 3 5
3 2 4 9
4 3 5 14
5 4 6 20

5 < 5 为假,循环退出,最终 total === 20。2 + 3 + 4 + 5 + 6 = 20,与课程要求完全吻合。

五、判题机制:四个断言是如何约束你的代码的

本挑战的 --hints-- 部分定义了自由代码判题系统会运行的 4 条 JavaScript 断言,理解它们能帮你弄清"为什么这样写算对、那样写算错"。这些断言在测试时基于学习者提交的代码、配合 freeCodeCamp 提供的 __helpers 工具对象执行,其中出现最频繁的两个辅助方法是 __helpers.removeJSComments(code)(剔除代码中的注释,防止注释里"伪造"答案)与 __helpers.removeWhiteSpace()(去除空白)。

  1. total 必须声明并初始化为 0:通过正则 /(var|let|const)\s*?total\s*=\s*0.*?;?/ 检查是否存在形如 let total = 0;var/const 亦可)的声明语句。也就是说必须先声明变量、初始值必须是 0
  2. total 必须等于 20:直接断言 assert(total === 20)。由于 myArr 的和确实是 20,这条等价于要求你的累加逻辑在给定数据上结果正确;
  3. 必须使用 for 循环遍历 myArr:通过 /for\s*\(/g 检测代码中出现了 for (,同时用 /myArr\s*\[/g 检测你确实通过 myArr[i] 形式按下标访问了数组。这一条同时排除了用 while 循环、forEachreduce 等替代方案——本课的教学目标就是让学习者练习 for 遍历;
  4. 不得直接给 total 赋值 20 来作弊:通过 !/...match(/total[=+-]0*[1-9]+/gm) 反向匹配,若检测到 total = 20 之类的硬编码(含复合赋值变形),断言即失败。

综合起来,四条断言恰好形成"声明→结果→手法→禁止捷径"的完整校验闭环,这正是 freeCodeCamp 自动评分设计思路的典型体现:既要结果正确,也要过程符合本课教学目标

六、常见错误与边界情况提醒

基于对循环边界与断言逻辑的理解,初学者在本挑战中最常见的失误包括:

  • 硬编码答案:直接写 total = 20,违背挑战意图且会被第 4 条断言拦截;
  • const myArr 重新声明:种子代码中 myArr 已是 const,在同一作用域重复声明会直接抛 SyntaxError;你只需在其下方使用它;
  • 条件写成 i <= myArr.length:多遍历一次会得到 total += undefined,结果为 NaN,断言 total === 20 失败;
  • 循环写成 i < 5 而不是 i < myArr.length:虽然对当前 5 元素数组"恰好也能跑通",但一旦测试数组规模改变(freeCodeCamp 有时会用更大数组重复校验)就会出错。正确的做法是始终基于 arr.length 表达边界,而不是写死数字;
  • 累加变量用 const 声明total += myArr[i] 会尝试改写 const 变量,运行时报 TypeError: Assignment to constant variable

七、延伸:这条知识链后续通向哪里

basic-javascript.json 的编排,本挑战之后会立刻进入:

  • Nesting For Loops(for 循环嵌套):处理二维数组(数组的数组),外层循环遍历行、内层循环遍历列;
  • Iterate with JavaScript Do...While Loops:do...while 至少执行一次循环体的特性;
  • Replace Loops using Recursion:用递归思维替代循环,涉及基线条件与调用栈。

即便在更现代的 JavaScript 中,数组还提供了 forEachmapfilterreduce 等高阶方法,但理解最底层的 for 循环下标遍历,仍是读懂这些方法内部机制、以及在没有这些方法的场景(或追求极致性能时)自己手写遍历的基础。

如何在仓库与学习平台中练习本挑战

  • 原始挑战源文件位于 curriculum/challenges/english/blocks/basic-javascript/5675e877dbd60be8ad28edc6.md,其 frontmatter 中 id: 5675e877dbd60be8ad28edc6forumTopicId: 18216 是它在数据库与论坛中的唯一标识;
  • 课程顺序与标题定义在 curriculum/structure/blocks/basic-javascript.json 中可查证;
  • 在学习平台上,你只需在编辑器内补全 // Only change code below this line 之后的代码并点击运行,即可看到 4 条断言逐条验证你的实现;
  • 也可以把参考实现粘贴到浏览器开发者工具的 Console 中独立运行,观察 total 的最终输出是否为 20,自行验证累加过程。

掌握"零基索引 + arr.length 边界 + 累加器"这一组合后,数组求和、计数、找最大值最小值、拼接字符串等大量基础算法题,就都有了统一的解题范式。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391