☰
Web-Dev-For-Beginners 第 4 课:JavaScript 数组与循环完全指南
2026/10/17 17:36:12 网站建设 项目流程

Web-Dev-For-Beginners 第 4 课:JavaScript 数组与循环完全指南

【免费下载链接】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 课程2-js-basics/4-arrays-loops一课展开,系统讲解 JavaScript 中两个最基础的数据处理概念:数组(Arrays)与循环(Loops)。从购物车条目、好友列表这类日常页面需求出发,你将学会用数组组织数据、用四种循环高效遍历数据,并掌握用数组方法完成统计、过滤、映射等现代数据处理技巧,最终能够在浏览器控制台与真实项目中写出可处理数百上千条数据的高效代码。

配图为课程官方 Sketchnote,出自 Tomomi Imura(引用自课程原文)。

数组:数据组织的基石

想象一个数字档案柜:不是每个抽屉放一份文件,而是把多个相关条目放进一个结构化容器。程序里的数组(Array)正是这样的容器——把多份信息打包保存在一个变量里。无论是做照片墙、待办清单,还是记录游戏高分榜,数组都是数据组织的基础。原文还留了一个小思考题:你能想到现实世界中数组的例子吗(比如太阳能电池板阵列 solar panel array)?

创建数组

创建数组非常简单,使用方括号[]即可:

// 空数组——就像等待装入商品的空购物车 const myArray = [];

也可以用初始值直接填充数组:

// 你的冰淇淋店口味菜单 const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"]; // 用户资料信息(混合不同类型数据) const userData = ["John", 25, true, "developer"]; // 你最喜欢的班级的测验成绩 const scores = [95, 87, 92, 78, 85];

需要注意的几个特点:

  • 同一个数组可以同时存放字符串、数字甚至布尔值;
  • 每个元素用逗号分隔,非常直观;
  • 数组非常适合把相关联的信息聚在一起。

数组索引:从 0 开始

初学时一个容易困惑的点是:数组编号从 0 开始,而不是 1。这种零基索引(zero-based indexing)源于计算机内存的寻址方式,从 C 语言时代起就成为编程惯例。数组中每个位置都有一个地址编号,称为索引(index)。

以iceCreamFlavors为例:

索引值描述
0"Chocolate"第一个元素
1"Strawberry"第二个元素
2"Vanilla"第三个元素
3"Pistachio"第四个元素
4"Rocky Road"第五个元素

访问数组元素:

const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"]; // 用方括号加索引号访问单个元素 console.log(iceCreamFlavors[0]); // "Chocolate" - 第一个元素 console.log(iceCreamFlavors[2]); // "Vanilla" - 第三个元素 console.log(iceCreamFlavors[4]); // "Rocky Road" - 最后一个元素

关键行为:使用方括号 + 索引号访问元素;计数从 0 开始,因此第一个元素是索引 0。

修改数组元素:

// 修改已有值 iceCreamFlavors[4] = "Butter Pecan"; console.log(iceCreamFlavors[4]); // "Butter Pecan" // 在末尾追加新元素 iceCreamFlavors[5] = "Cookie Dough"; console.log(iceCreamFlavors[5]); // "Cookie Dough"

这里展示了两个特性:把索引 4 的值从 "Rocky Road" 改成 "Butter Pecan";在索引 5 处新增元素——当写入位置超出当前边界时,数组长度会自动扩展。

数组长度与常用方法

数组自带一些内建属性与方法,让数据处理轻松不少。

获取数组长度:

const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"]; console.log(iceCreamFlavors.length); // 5 // 数组变化时 length 自动更新 iceCreamFlavors.push("Mint Chip"); console.log(iceCreamFlavors.length); // 6

要点:length返回数组元素总数;增删元素时自动更新;这个动态计数对循环边界和输入校验非常有用。

核心数组方法:

const fruits = ["apple", "banana", "orange"]; // 添加元素 fruits.push("grape"); // 追加到末尾: ["apple", "banana", "orange", "grape"] fruits.unshift("strawberry"); // 插入到开头: ["strawberry", "apple", "banana", "orange", "grape"] // 删除元素 const lastFruit = fruits.pop(); // 删除末尾并返回 "grape" const firstFruit = fruits.shift(); // 删除开头并返回 "strawberry" // 查找元素 const index = fruits.indexOf("banana"); // 返回 1("banana" 所在位置) const hasApple = fruits.includes("apple"); // 返回 true

理解这组方法:push()/unshift()分别向末尾、开头添加元素;pop()/shift()分别从末尾、开头删除并返回元素;indexOf()定位元素位置,includes()判断元素是否存在。它们会返回被删元素或位置索引等有价值的信息。

循环:让重复劳动自动化

可以想象狄更斯小说里学生反复抄写句子的经典惩罚——如果只需下一条指令"把这句话写 100 遍"就能自动完成,这正是循环为代码做的事。循环就像一个不知疲倦的助手,无论是逐个检查购物车商品,还是展示相册里的每张照片,它都能高效地处理重复任务。

JavaScript 提供多种循环,本课逐一讲解它们的适用场景。

for 循环:可预测的重复

for循环像设定一个闹钟——你精确知道要执行多少次,非常适合处理数组和计数场景。

for 循环的三段式结构:

组成部分作用示例
初始化(Initialization)设定起点let i = 0
条件(Condition)何时继续i < 10
递增(Increment)如何更新i++
// 从 0 数到 9 for (let i = 0; i < 10; i++) { console.log(`Count: ${i}`); } // 更实际的例子:处理成绩 const testScores = [85, 92, 78, 96, 88]; for (let i = 0; i < testScores.length; i++) { console.log(`Student ${i + 1}: ${testScores[i]}%`); }

执行流程拆解:开头初始化计数器i为 0;每次迭代前检查条件i < 10;条件为真时执行代码块;每次迭代后通过i++使i加 1;当条件为假(i达到 10)时循环终止。

常见的for循环变体模式包括for(let i = 0; i < n; i++)(正向计数)、for(let i = n-1; i >= 0; i--)(反向遍历)以及for(let i = 0; i < arr.length; i += 2)(跳跃式步进)。

while 循环:条件驱动的重复

while循环就像说"一直做这件事,直到……"——你不一定知道它跑多少次,但知道何时该停。它非常适合反复询问用户输入直到满足要求、或搜索数据直到找到目标这类场景。

while 循环的特性:

  • 只要条件为真就持续执行;
  • 计数器变量需要手动管理;
  • 每次迭代前先检查条件;
  • 若条件永远不为假,存在死循环风险。
// 基础计数示例 let i = 0; while (i < 10) { console.log(`While count: ${i}`); i++; // 别忘了递增! } // 更实际的例子:处理用户输入 let userInput = ""; let attempts = 0; const maxAttempts = 3; while (userInput !== "quit" && attempts < maxAttempts) { userInput = prompt(`Enter 'quit' to exit (attempt ${attempts + 1}):`); attempts++; } if (attempts >= maxAttempts) { console.log("Maximum attempts reached!"); }

要点:计数器i在循环体内手动管理;通过递增防止死循环;第二个例子演示了用户输入 + 尝试次数上限的实战模式,内置了防死循环的安全机制。安全第一:while 循环强大但要求仔细管理条件,务必确保循环条件最终会变为假——常见防御手段包括修改条件变量、加入逃生条件和设置最大迭代上限。

现代循环写法:for...of 与 forEach

ES6+ 提供了更现代、更不易出错的循环语法。

for...of 循环:

const colors = ["red", "green", "blue", "yellow"]; // 现代写法——更简洁也更安全 for (const color of colors) { console.log(`Color: ${color}`); } // 对比传统 for 循环 for (let i = 0; i < colors.length; i++) { console.log(`Color: ${colors[i]}`); }

for...of的核心优势:省去索引管理,杜绝 off-by-one(差一错误);直接拿到数组元素本身;显著提升可读性、降低语法复杂度。

forEach 方法:

const prices = [9.99, 15.50, 22.75, 8.25]; // 用 forEach 实现函数式编程风格 prices.forEach((price, index) => { console.log(`Item ${index + 1}: $${price.toFixed(2)}`); }); // 配合箭头函数做简单操作 prices.forEach(price => console.log(`Price: $${price}`));

关于forEach需要知道:它为每个数组元素执行一次回调函数;回调可同时接收元素值和索引两个参数;它无法中途提前终止(区别于传统循环);返回值是undefined(不会创建新数组)。

数组与循环的组合:数据处理实战

数组 + 循环是无数编程任务的基础组合,从展示列表到计算统计都离不开它。

传统数组遍历的两种写法:

const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"]; // 经典 for 循环写法 for (let i = 0; i < iceCreamFlavors.length; i++) { console.log(`Flavor ${i + 1}: ${iceCreamFlavors[i]}`); } // 现代 for...of 写法 for (const flavor of iceCreamFlavors) { console.log(`Available flavor: ${flavor}`); }

两种写法各有取舍:传统写法用length决定循环边界、按索引访问元素;for...of直接拿到元素。无论哪种,每个元素都恰好被处理一次。

数据统计实战:一次循环算出平均分、最高分、最低分

const studentGrades = [85, 92, 78, 96, 88, 73, 89]; let total = 0; let highestGrade = studentGrades[0]; let lowestGrade = studentGrades[0]; // 用单次循环处理全部成绩 for (let i = 0; i < studentGrades.length; i++) { const grade = studentGrades[i]; total += grade; if (grade > highestGrade) { highestGrade = grade; } if (grade < lowestGrade) { lowestGrade = grade; } } const average = total / studentGrades.length; console.log(`Average: ${average.toFixed(1)}`); console.log(`Highest: ${highestGrade}`); console.log(`Lowest: ${lowestGrade}`);

这段代码的运行逻辑:初始化总和与极值的追踪变量;用单次高效循环处理每条成绩;累加总和用于计算平均分;迭代过程中同步追踪最高、最低值;循环结束后计算最终统计结果。这就是四种核心处理模式的雏形——累加求和、极值比较、条件过滤、数据映射。

源码佐证:数组与循环在真实项目中的运用

这些概念不只是课堂练习,本仓库的多个实战项目就是最好的证据。以太空射击游戏为例,在 6-space-game/solution/app.js 中:

  • 游戏用enemies、bullets、particles三个数组维护所有动态实体,敌人生成时调用enemies.push({...})(app.js),发射子弹时调用bullets.push({...})(app.js),爆炸效果则用for循环生成大量粒子后逐个particles.push(...)(app.js);
  • 渲染循环用for (const e of enemies)(app.js)、for (const b of bullets)(app.js)、for (const p of particles)(app.js)——这正是本课讲到的for...of直接遍历数组的实战用法;
  • 排行榜功能读取localStorage中的分数数组,list.push({...})写入新成绩、list.sort(...)排序后截取前 10 名,最后用list.forEach(item => {...})(app.js)把每条记录渲染成 DOM 列表项。

银行项目的 7-bank-project/solution/app.js 中也能看到for (const id of ids)(app.js)和for (const tx of sorted)(app.js)这类for...of遍历。可见"数组组织数据、循环遍历数据"正是这些可运行项目共同的底层骨架。

动手挑战

GitHub Copilot Agent Challenge

使用 Copilot 的 Agent 模式完成以下挑战:构建一个综合数据处理函数,把数组与循环结合起来分析数据集并产出有意义的统计结果。

Prompt:创建一个名为analyzeGrades的函数,接收一个学生成绩对象数组(每个对象含name和score属性),返回一个统计对象,包含最高分、最低分、平均分、及格人数(score >= 70)以及成绩高于平均分的学生姓名数组。解决方案中至少使用两种不同的循环类型。

挑战:用现代数组方法重构

JavaScript 提供了多种可替代传统循环的现代数组方法:forEach、for...of、map、filter、reduce。尝试用至少三种数组方法重构上面的学生成绩示例,观察现代 JavaScript 语法让代码变得多么简洁易读。

例如,用map做变换、filter做过滤、reduce做累加,往往一行就能取代整个传统循环体。

课后作业:Loop an Array

课程的配套作业见 2-js-basics/4-arrays-loops/assignment.md,共四个递进练习:

  1. 数字模式生成器:用带自定义步进(increment)的for循环列出 1–20 之间所有 3 的倍数(预期输出3, 6, 9, 12, 15, 18);
  2. 数组分析:创建至少 8 个数字的数组,编写findMaximum()、findMinimum()、calculateSum()三个函数并测试(加分项:找出第二大的数);
  3. 字符串数组处理:创建至少 5 个字符串(电影/书/歌名),分别用传统for循环带序号输出、用for...of转大写输出、用forEach统计总字符数;
  4. 数据过滤(进阶):创建至少 5 个含name、age、grade属性的学生对象数组,用循环筛选 18 岁以上学生、计算平均成绩、生成成绩高于 85 的新数组。

作业还给出了提交要求(带注释的代码、运行截图/文本输出、说明每项任务选用的循环类型及理由)和评价量表(功能性、代码质量、注释、循环用法多样性、测试充分性各 3 分),并留下反思问题:哪种循环最顺手?处理数组时遇到什么困难?这些技能如何应用到真实 Web 开发中?

复习与自测

  • 数组从 0 开始计数而非 1,你能说出背后的原因吗?
  • 访问不存在的索引(比如在 5 元素数组里访问arr[100])会发生什么?
  • 想出三个真实世界中适合用数组的场景;
  • for...of相比传统for循环有哪些优势?什么时候你仍会倾向传统写法?
  • forEach和map有什么区别(提示:返回值)?
  • 忘记写i++会发生什么?while 循环的主要风险是什么,如何防止死循环?

本仓库的对应课程文件(英文原版)位于 2-js-basics/4-arrays-loops/README.md,本文基于的丹麦语翻译版位于 translations/da/2-js-basics/4-arrays-loops/README.md。建议在浏览器控制台中亲手创建并操作自己的数组——从最基础的方括号创建,到索引访问、push/pop/slice/splice等方法的组合运用,再到把四种循环与数组方法结合完成真实的数据统计任务。掌握数组与循环,你就拥有了几乎所有动态网页、移动应用与数据驱动应用共同依赖的规模化数据处理能力。

【免费下载链接】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),仅供参考

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

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

立即咨询