news 2026/6/9 9:28:58

跟着 MDN 学JavaScript day_16:技能测试——循环实战演练

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跟着 MDN 学JavaScript day_16:技能测试——循环实战演练

引言

理论知识的学习为我们搭建了理解循环的框架,但真正的编程能力需要在解决具体问题的过程中锤炼。今天,我们进入循环的技能测试环节,通过三道精心设计的题目来检验你是否真正掌握了forwhiledo...while循环的用法,以及breakcontinue语句在循环控制中的作用。

这些题目不仅考察循环本身,还会涉及 DOM 操作、数组遍历、对象属性访问以及条件判断等综合知识。三道题目各自要求使用不同的循环类型,这种设计迫使我们必须灵活切换思维模式,而不是机械地套用一种结构。让我们逐一拆解这些题目,在实战中巩固循环的运用能力。


一、实用的 DOM 操作

在开始解题之前,我们需要了解一个贯穿三道题目的基础技能,那就是使用 JavaScript动态创建和操作 HTML 元素。虽然本课程尚未系统地讲解 DOM 操作,但这三道题目都要求我们通过 JavaScript 来创建新元素、设置其内容并将其添加到页面中。

三个核心 API

API作用示例
document.createElement()创建一个新的 HTML 元素document.createElement('li')
element.textContent设置或获取元素的文本内容listItem.textContent = 'tomatoes'
parent.appendChild()将子元素追加到父元素中list.appendChild(listItem)
  • createElement()的参数是标签名称的字符串:'ul'创建无序列表、'li'创建列表项、'p'创建段落;
  • 创建出来的元素需要通过appendChild()方法添加到页面中某个已有的父元素里,才能最终显示在屏幕上;
  • 元素内部的文本内容通过textContent属性来设置。

这三个 API 组合起来,就构成了用 JavaScript 动态生成页面内容的最小工具集。在第一题中,我们需要创建多个列表项并将它们逐个追加到列表中;在第二题中,我们需要将搜索结果写入一个段落并追加到展示区域;第三题同样需要将找到的质数结果写入段落。理解这个基本的 DOM 操作流程是顺利解答三道题目的前提


二、循环 1:遍历数组并生成列表

第一道题目为我们设定了这样一个场景:有一个名为myArray的数组,里面存储了五种食材的字符串,包括西红柿、鹰嘴豆、洋葱、大米和黑豆。同时,起始代码已经帮我们创建好了一个空的无序列表元素list,我们可以在 JavaScript 中直接使用它。

2.1 任务目标

编写一个循环,遍历myArray中的每一个元素,完成以下操作:

  1. 为每个元素创建一个列表项(<li>元素);
  2. 将当前数组元素的值赋给列表项的文本内容;
  3. 将这个列表项追加到list无序列表中。

最终,list会被起始代码自动添加到页面的展示区域。

constmyArray=['tomatoes','chick peas','onions','rice','black beans'];constlist=document.createElement('ul');// Add your code here// Don't edit the code below here!constsection=document.querySelector('section');section.appendChild(list);

2.2 解题思路与代码实现

这道题考察的是最基本的for循环配合数组遍历的模式:

for(leti=0;i<myArray.length;i++){constlistItem=document.createElement('li');listItem.textContent=myArray[i];list.appendChild(listItem);}

执行流程

迭代imyArray[i]操作
第1次0'tomatoes'创建<li>tomatoes</li>并追加到<ul>
第2次1'chick peas'创建<li>chick peas</li>并追加
第3次2'onions'创建<li>onions</li>并追加
第4次3'rice'创建<li>rice</li>并追加
第5次4'black beans'创建<li>black beans</li>并追加
终止55 < 5false,循环结束

DOM 操作三步走

createElement('li') → textContent = myArray[i] → list.appendChild(listItem) 创建元素 设置文本内容 追加到父元素

这道题虽然简单,但它完美地展示了循环在动态生成页面内容时的核心作用——我们不需要手动编写五个<li>标签,只需要一个循环就能处理任意长度的数组。如果将来食材列表扩展到五十种,代码依然只有这几行,完全不需要改动。这就是循环所带来的可扩展性的力量


三、循环 2:搜索电话簿并提前退出

第二道题目将我们带入了一个更贴近实际应用的场景。我们有一个电话簿数组phonebook,其中每个元素都是一个对象,包含namenumber两个属性。题目要求使用一种在上一道任务中没有使用过的循环类型(即不能用普通for循环)。

3.1 任务目标

在电话簿中搜索给定的名字('Mustafa'),如果找到了匹配的联系人:

  1. 将该联系人的名字和电话号码输出到段落para中;
  2. 使用break语句立即退出循环,不再继续搜索后续条目。
constname='Mustafa';constpara=document.createElement('p');constphonebook=[{name:'Chris',number:'1549'},{name:'Li Kang',number:'9634'},{name:'Anne',number:'9065'},{name:'Francesca',number:'3001'},{name:'Mustafa',number:'6888'},{name:'Tina',number:'4312'},{name:'Bert',number:'7780'},{name:'Jada',number:'2282'},]// Add your code here// Don't edit the code below here!constsection=document.querySelector('section');section.appendChild(para);

3.2 解题思路与代码实现

既然不能用for循环,自然的选择就是while循环:

leti=0;while(i<phonebook.length){if(phonebook[i].name===name){para.textContent=`${phonebook[i].name}'s number is${phonebook[i].number}.`;break;}i++;}

while循环三要素的分布

要素在代码中的位置具体写法
初始化器循环之前let i = 0
退出条件while括号内i < phonebook.length
最终表达式循环体末尾i++

执行流程

i=0 → Chris ≠ Mustafa → i++ → 继续 i=1 → Li Kang ≠ Mustafa → i++ → 继续 i=2 → Anne ≠ Mustafa → i++ → 继续 i=3 → Francesca≠ Mustafa → i++ → 继续 i=4 → Mustafa = Mustafa → 输出结果 → break → 循环终止! i=5 → (永远不会到达,已经被 break 终止)

3.3 关键细节:break 的价值

如果没有break语句,即使已经找到了 Mustafa,循环仍然会继续遍历后面的 Tina、Bert 和 Jada,做无意义的检查。对于只有 8 条记录的电话簿来说这无关紧要,但如果电话簿有 10000 条记录而目标恰好在前 10 条,break就能节省 99.9% 的循环时间。

这道题的核心价值在于让我们体会while循环与break语句配合使用的典型场景:处理一个需要提前退出的线性查找任务。while循环将计数器的管理逻辑分散开来,在某些场景下这种分散反而让搜索逻辑更加清晰。


四、循环 3:倒序筛选质数

第三道题目在逻辑上最为复杂,它融合了倒序遍历条件过滤以及continue语句的运用。题目要求使用一种在前两个任务中没有使用过的循环类型,排除了forwhile

4.1 任务目标

  • 变量i初始值为500,被明确指定为迭代器;
  • 变量para是一个已创建好的段落元素,用于输出结果;
  • 函数isPrime(num)用于判断传入的数字是否为质数(是质数返回true,不是则返回false);

任务要求:

  1. 使用循环倒序(从大到小)遍历从 2 到 500 的所有数字;
  2. 对于每个数字,调用isPrime()进行检测;
  3. 如果不是质数,使用continue跳过当前迭代,不执行输出;
  4. 如果是质数,则将该数字追加到para.textContent中,用分隔符隔开。

质数:大于 1 且只能被 1 和自身整除的自然数(1 不算质数)。

leti=500;constpara=document.createElement('p');functionisPrime(num){for(leti=2;i<num;i++){if(num%i===0){returnfalse;}}returntrue;}// Add your code here// Don't edit the code below here!constsection=document.querySelector('section');section.appendChild(para);

4.2 解题思路与代码实现

既然forwhile都已经被前两道题使用过了,剩下的选择就是do...while循环:

do{if(!isPrime(i)){i--;continue;}para.textContent+=`${i},`;i--;}while(i>=2);

do...while循环三要素的分布

要素在代码中的位置具体写法
初始化器循环之前let i = 500(题目已提供)
退出条件while括号内(循环末尾)i >= 2
最终表达式循环体末尾i--(出现在两处)

执行流程图解

i=500 → 进入循环体 ├─ isPrime(500)? → false → i-- (i=499) → continue → 回到 while 检查 ├─ i=499 → isPrime(499)? → true → 追加 "499, " → i-- (i=498) ├─ i=498 → isPrime(498)? → false → i-- (i=497) → continue ├─ i=497 → isPrime(497)? → ... └─ ... 重复直到 i=1 → 退出条件 i >= 2 为 false → 循环终止

4.3 ⚠️ 关键陷阱:continue 与计数器的顺序

这道题最易出错的地方在于continue语句的使用位置。看下面的对比:

// ❌ 错误!会导致无限循环do{if(!isPrime(i)){continue;// 直接跳到 while 检查,i 没有递减!}para.textContent+=`${i},`;i--;}while(i>=2);// ✅ 正确:在 continue 之前先递减 ido{if(!isPrime(i)){i--;// 先递减计数器continue;// 再跳过本次迭代}para.textContent+=`${i},`;i--;}while(i>=2);

原理continue会跳过循环体内剩余的代码,直接跳转到while条件检查。如果在continue之前没有更新ii将永远不变,退出条件永远无法满足,从而导致无限循环。这是一个非常常见的陷阱,务必牢记:

在循环中使用continue时,必须确保迭代器在continue之前已经更新。


五、三道题目综合对比

对比维度循环 1循环 2循环 3
循环类型forwhiledo...while
遍历方向正序(0 → n)正序(0 → n)倒序(500 → 2)
循环控制自然结束break提前退出continue跳过迭代
数据结构字符串数组对象数组数值 + 函数判断
DOM 操作创建多个<li>写入单个<p>拼接写入<p>
核心考点基本遍历 + 动态生成线性查找 + 提前退出条件过滤 + 倒序递减

六、常见错误与避坑指南

6.1 忘记初始化计数器

// ❌ 错误while(i<phonebook.length){...}// i 未定义!// ✅ 正确leti=0;while(i<phonebook.length){...}

6.2 忘记在循环体中更新计数器

// ❌ 错误:无限循环!leti=0;while(i<5){console.log(i);// 忘记 i++!}// ✅ 正确leti=0;while(i<5){console.log(i);i++;}

6.3 退出条件写反

// ❌ 错误:循环一次都不执行do{para.textContent+=i;i--;}while(i<=2);// i 初始为 500,条件立假// ✅ 正确do{para.textContent+=i;i--;}while(i>=2);

总结

完成这三道技能测试题,我们经历了一次从基础到进阶的循环实战训练。

题目循环类型核心技能关键收获
生成食材列表for遍历数组 + DOM 动态创建循环的可扩展性——代码行数与数据规模解耦
搜索电话簿while对象属性访问 +break线性查找中提前退出的性能优化模式
筛选质数do...while倒序遍历 +continuecontinue前必须更新计数器,避免无限循环

三道题目覆盖了三种不同的循环结构,每一种都在特定的场景下展现出其独特的价值。更重要的是,它们共同揭示了循环编程中必须时刻留意的核心原则:

  1. 清晰的初始化——计数器从哪开始?
  2. 正确的退出条件——什么时候停止?边界情况对吗?
  3. 可靠的迭代器更新——每次迭代是否都向退出条件靠近?

当你能够根据问题的特性自如地选择最合适的循环类型,并正确处理提前退出(break)与跳过迭代(continue)的逻辑时,你就真正掌握了 JavaScript 中循环的精髓。


还在为 JavaScript 代码写得像“意大利面条”、逻辑混乱难以维护而头秃?收藏本文持续跟进,后续将系统分享 JS 高效语法糖、浏览器兼容与 Polyfill 实战、手写核心源码解析、常见坑点避雷指南,从基础语法到进阶逻辑一站式打通,助你快速提升前端开发硬实力!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 9:28:34

从零搭建企业网:手把手教你用eNSP模拟千人校园网络规划

从零搭建企业网&#xff1a;手把手教你用eNSP模拟千人校园网络规划当第一次接触企业级网络规划时&#xff0c;很多人会被复杂的拓扑结构和专业术语吓退。但事实上&#xff0c;只要掌握正确的方法论和工具&#xff0c;即使是千人规模的校园网络也能通过模拟环境轻松搭建。华为eN…

作者头像 李华
网站建设 2026/6/9 9:23:47

AI建站工具选型指南:3大维度对比,找到最适合你的那个

AI建站工具选型指南&#xff1a;3大维度对比&#xff0c;找到最适合你的那个面对市面上五花八门的AI建站工具&#xff0c;很多用户都会陷入选择困难&#xff1a;有的号称全AI生成&#xff0c;有的主打模板丰富&#xff0c;还有的低价吸引人。到底哪个靠谱&#xff1f;哪个最适合…

作者头像 李华
网站建设 2026/6/9 9:22:56

别再手动输坐标了!用Excel+Arcmap批量导入点位,5分钟搞定一张地图

ExcelArcmap批量导入点位全攻略&#xff1a;从数据整理到地图生成的高效工作流每次面对成百上千个点位坐标时&#xff0c;手动输入不仅耗时耗力&#xff0c;还容易出错。本文将带你掌握一套完整的Excel预处理与Arcmap批量导入技术方案&#xff0c;让地图制作效率提升10倍以上。…

作者头像 李华
网站建设 2026/6/9 9:22:01

从传感器噪声到平滑点云:一篇讲透深度相机数据处理的‘内功心法’

深度相机数据处理实战&#xff1a;从噪声抑制到边缘修复的完整方法论深度相机在工业质检、机器人抓取和AR/VR等领域的应用越来越广泛&#xff0c;但原始数据质量往往成为制约精度的瓶颈。物体边缘数据丢失、深度值跳变和时序不稳定等问题&#xff0c;让许多工程师在项目落地时遭…

作者头像 李华
网站建设 2026/6/9 9:20:44

LLM生产系统合规落地:分层治理架构与工程实践

1. 项目概述&#xff1a;当大模型真正开始“上班”&#xff0c;它得先学会签劳动合同“Ethics Meets Efficiency”这个标题不是修辞游戏&#xff0c;而是我过去18个月在三家不同规模AI团队落地LLM生产系统时&#xff0c;每天早上站会第一句真实提问&#xff1a;“今天上线的这个…

作者头像 李华