跟着 MDN 学JavaScript day_20:函数技能测试与实战解析
引言
在 JavaScript 的学习旅程中,函数是无可争议的核心支柱。它们不仅帮助我们封装可复用的逻辑,更是通往高阶编程范式的大门。MDN 的技能测试环节提供了一系列经典的实战练习,从基础的函数定义到高级的数组方法与箭头函数重构,层层递进。本文将深入解析这四个挑战任务,并探讨它们背后的 DOM 操作与编程思维。
一、DOM 操作:连接逻辑与界面的桥梁
在进行本次函数测试之前,部分题目需要借助 DOM 操作来完成任务。在实际开发中,函数往往不是孤立的纯逻辑单元,它们需要从页面获取输入,并将计算结果渲染到页面上。
本题中涉及的 DOM 操作相对基础:
| API | 用途 |
|---|---|
document.querySelector("p") | 选中页面上的第一个段落元素 |
element.textContent | 读取或修改元素的文本内容 |
这种模式反映了前端开发的基本范式:通过 JavaScript 选中节点 → 读取或修改其状态 → 驱动用户界面变化。
二、任务一:基础函数定义与随机逻辑封装
任务描述
定义一个名为chooseName()的函数,从预定义的姓名数组中随机选取一个名字,并将其显示在页面上的段落元素中。
constnames=["Chris","Li Kang","Anne","Francesca","Mustafa","Tina","Bert","Jada",];constpara=document.querySelector("p");// 在此处补全代码chooseName();解题思路
- 生成随机数组索引:
Math.random()生成[0, 1)的浮点数,乘以names.length后得到[0, length)范围,Math.floor()向下取整得到有效整数索引 - 用索引取值并赋给
para.textContent
functionchooseName(){constrandomIndex=Math.floor(Math.random()*names.length);constrandomName=names[randomIndex];para.textContent=randomName;}chooseName();核心收获:将一段具有特定功能的代码封装起来,通过一次调用即可执行,避免重复编写相同逻辑。
三、任务二:Canvas 绘图与函数参数化![]()
任务描述
创建一个函数,根据传入的坐标、尺寸和颜色参数,在 Canvas 画布上绘制一个矩形。
constcanvas=document.querySelector("canvas");constctx=canvas.getContext("2d");constx=50;consty=60;constwidth=100;constheight=75;constcolor="blue";// 在此处补全代码解题思路
函数通过参数接收外部数据,内部只关心通用绘图逻辑。fillRect()接收四个参数:横坐标、纵坐标、宽度、高度,与题目变量完美对应。
functiondrawRectangle(x,y,width,height,color){ctx.fillStyle=color;ctx.fillRect(x,y,width,height);}drawRectangle(x,y,width,height,color);| 参数 | 用途 | 传入值 |
|---|---|---|
x | 矩形左上角横坐标 | 50 |
y | 矩形左上角纵坐标 | 60 |
width | 矩形宽度 | 100 |
height | 矩形高度 | 75 |
color | 填充颜色 | "blue" |
核心收获:设计良好的函数应当通过参数来接受外部数据,内部只关心通用逻辑的实现,同一个函数可以绘制出无数种不同外观和位置的矩形。
四、任务三:函数的返回值与单一职责
任务描述
对任务一进行深度重构,引入两个软件设计原则:单一职责和函数返回值。
原始chooseName()函数包揽了三件事:生成随机数、选取名字、修改页面内容。这种"全能函数"难以测试和复用。
constnames=["Chris","Li Kang","Anne","Francesca","Mustafa","Tina","Bert","Jada",];constpara=document.querySelector("p");// 在此处补全代码重构目标
| 函数 | 职责 | 输入 | 输出 |
|---|---|---|---|
random(min, max) | 生成指定范围的随机整数 | min,max | 随机整数 |
chooseName(array) | 从数组中随机选取一个元素 | 数组 | 选中的元素 |
重构后的代码
functionrandom(min,max){returnMath.floor(Math.random()*(max-min+1))+min;}functionchooseName(array){constrandomIndex=random(0,array.length-1);returnarray[randomIndex];}// 在函数外部将数据处理结果渲染到页面constselectedName=chooseName(names);para.textContent=selectedName;设计对比
❌ 重构前(全能函数): chooseName() ├── 生成随机数 ├── 选取名字 └── 修改 DOM ✅ 重构后(职责分离): random(min, max) → 纯数据计算,返回随机整数 chooseName(array) → 纯数据选取,返回名字 外部代码 → DOM 渲染核心收获:
random()现在可用于任何需要随机整数的场景,复用性极大提升;chooseName()成为纯粹的数据处理函数,输入确定则输出确定,易于测试;- 数据处理逻辑与界面展示逻辑彻底分离,符合前端开发的关注点分离原则。
五、任务四:箭头函数与数组过滤的简洁之道
任务描述
聚焦于 ES6 箭头函数及其在数组回调方法中的优雅应用。原始代码定义了一个独立的命名函数isShort(),要求将其以内联箭头函数的形式直接写入filter()调用中,越简洁越好。
constnames=["Chris","Li Kang","Anne","Francesca","Mustafa","Tina","Bert","Jada",];constpara=document.querySelector("p");// 在此处补全代码从具名函数到箭头函数
// 原始写法:独立的具名函数functionisShort(name){returnname.length<5;}constshortNames=names.filter(isShort);// 写法一:完整箭头函数constshortNames=names.filter((name)=>{returnname.length<5;});// 写法二:省略花括号和 returnconstshortNames=names.filter((name)=>name.length<5);// 写法三:最简洁——单参数省略括号constshortNames=names.filter(name=>name.length<5);箭头函数简写规则
| 场景 | 完整写法 | 简写 |
|---|---|---|
| 单个参数 | (name) => | name => |
| 单行返回 | { return expr; } | expr |
最终代码
constshortNames=names.filter(name=>name.length<5);para.textContent=shortNames;// 输出:Chris, Anne, Tina, Bert, Jada(长度小于5的名字)核心收获:从具名函数到箭头函数的内联重构,不仅是语法糖的使用,更代表了 JavaScript 社区向函数式编程、声明式编程风格演进的趋势。代码更紧凑,核心逻辑 “过滤出长度小于5的名字” 更加聚焦。
总结
MDN 的这一系列函数测试,精心设计了一条从基础到进阶的学习路径:
| 任务 | 核心技能 | 关键收获 |
|---|---|---|
| 任务一 | 函数定义 + 随机数 | 基本封装,一次定义多次调用 |
| 任务二 | 参数化函数 + Canvas | 通过参数让函数通用化 |
| 任务三 | 返回值 + 单一职责 | 数据逻辑与DOM渲染分离 |
| 任务四 | 箭头函数 +filter | 声明式编程,简洁表达 |
掌握这些逐步递进的模式,对于写出高质量、易维护的 JavaScript 代码至关重要。
还在为 JavaScript 代码写得像“意大利面条”、逻辑混乱难以维护而头秃?收藏本文持续跟进,后续将系统分享 JS 高效语法糖、浏览器兼容与 Polyfill 实战、手写核心源码解析、常见坑点避雷指南,从基础语法到进阶逻辑一站式打通,助你快速提升前端开发硬实力!
