☰
JavaScript 代码风格实战:从《不好的风格》练习看如何识别并修复代码风格问题
2026/10/6 7:43:08 网站建设 项目流程
  • 文档
  • 教程
  • 前端

【免费下载链接】zh.javascript.info

现代 JavaScript 教程(The Modern JavaScript Tutorial),以最新的 ECMAScript 规范为基准,通过简单但足够详细的内容,为你讲解从基础到高阶的 JavaScript 相关知识。

项目地址:https://gitcode.com/gh_mirrors/zh/zh.javascript.info
点击查看免费下载

本文基于 zh.javascript.info(现代 JavaScript 教程)代码质量章节中的实战练习展开。该练习给出了一段“风格很差但功能正确”的pow幂函数代码,要求读者逐行找出风格问题并修复。读完本文,你将能系统地识别函数签名空格、花括号位置、运算符两侧空格、分号缺失、超长行、多变量声明等常见风格缺陷,并掌握一套可直接套用的修复方法;文中还会结合 代码风格主文 的规则体系与 ESLint 等自动检查工具,帮助你建立可落地的代码风格习惯。

练习背景:它在教程中的位置与考察目标

这段练习位于教程的 1-js/03-code-quality/02-coding-style 目录下,是“代码风格”一章的第一个任务,题目本身存放在 task.md,参考答案存放在 solution.md。

该章的核心主张非常明确:“我们的代码必须尽可能的清晰和易读”,良好的代码风格是一项“编程艺术”——以正确且易于他人阅读的方式完成复杂任务。练习的目的正是把这一抽象原则落到具体代码上:题目给出的代码在语法上完全合法、能正确计算x的n次幂,但充斥着大量风格缺陷。学习者需要像“审稿人”一样,逐行挑出问题并给出修复版本。

原始代码:一段“能跑但难看”的 pow 函数

练习给出的原始代码如下(这就是 task.md 中待修复的版本):

function pow(x,n) { let result=1; for(let i=0;i<n;i++) {result*=x;} return result; } let x=prompt("x?",''), n=prompt("n?",'') if (n<=0) { alert(`Power ${n} is not supported, please enter an integer number greater than zero`); } else { alert(pow(x,n)) }

功能上它完成了三件事:定义pow(x, n)幂函数;通过两次prompt获取x与n;当n <= 0时提示不支持,否则弹出计算结果。但这段代码在可读性上有大量问题,接下来我们对照 solution.md 中逐条标注的注释,逐一剖析。

逐条剖析:代码中的每一处风格缺陷

下面是在原始代码上标注出的全部问题。为了方便对照,先看带注释的完整版本:

function pow(x,n) // <- 参数之间没有空格 { // <- 花括号独占了一行 let result=1; // <- = 号两边没有空格 for(let i=0;i<n;i++) {result*=x;} // <- 没有空格 // { ... } 里面的内容应该在新的一行上 return result; } let x=prompt("x?",''), n=prompt("n?",'') // <-- 从技术的角度来看是可以的, // 但是拆分成 2 行会更好,并且这里也缺了空格和分号 ; if (n<=0) // <- (n <= 0) 里面没有空格,并且应该在本行上面加一个空行 { // <- 花括号独占了一行 // 下面的一行代码太长了,可以将其拆分成 2 行以提高可读性 alert(`Power ${n} is not supported, please enter an integer number greater than zero`); } else // <- 可以像 "} else {" 这样写在一行上 { alert(pow(x,n)) // 缺失了空格和分号 ; }

缺陷一:函数签名中参数之间没有空格

function pow(x,n)中x与n之间缺少空格。教程的 代码风格主文 将“空格”视为代码风格的基础语法要素,并提供了完整的风格备忘图(见下图),其中明确要求:函数名与左括号之间、括号与参数之间都要有空格,参数之间也要有空格。

修复方式:function pow(x, n)。

缺陷二:花括号独占一行

原始代码把左花括号{放在了单独一行:

function pow(x,n) {

主文在“花括号”一节中明确指出:在大多数 JavaScript 项目中,花括号采用“Egyptian” 风格(即 K&R 风格)—— 左花括号与相应的关键词位于同一行末尾,而不是另起一行,且左括号前应有一个空格:

if (condition) { // do this // ...and that }

因此{应紧跟函数签名:function pow(x, n) {。类似的错误在后面的if (n<=0)与else块中重复出现,属于同一类问题。

缺陷三:赋值运算符=两侧没有空格

let result=1;中=两侧没有空格。主文要求“运算符周围要有空格”,这是提高可读性的基础规则。修复为let result = 1;。

缺陷四:for 循环整体压缩在一行、缺少空格、代码块未换行

for(let i=0;i<n;i++) {result*=x;}同时违反了几条规则:

  • for关键字与左括号之间没有空格(主文要求for、if、while等关键词后留空格);
  • 循环头部i=0、i<n、i++内部以及分号后缺少空格;
  • 循环体{result*=x;}被压在同一行。主文明确指出:{ ... }里面的内容应该在新的一行上。

修复为:

for (let i = 0; i < n; i++) { result *= x; }

缺陷五:用逗号在一行内声明多个变量

let x=prompt("x?",''), n=prompt("n?",'')在语法上完全合法(这也是原注释所说“从技术的角度来看是可以的”),但把两次prompt挤在同一行,既缺空格、又缺分号,可读性差。拆成两行、每行一个变量声明更清晰:

let x = prompt("x?", ""); let n = prompt("n?", "");

缺陷六:if 条件内部没有空格,且上方缺少空行

if (n<=0)中n<=0内部没有空格(应为n <= 0)。同时,这段if之前的let声明与if之间没有空行。主文在“缩进”一节中专门讲了垂直方向上的缩进:用空行把代码拆分成逻辑块。即使是一个函数,也应分割为“变量初始化 → 主逻辑 → 返回值”等逻辑块;写代码时不应出现连续超过 9 行都没有被垂直分割的情况。

因此,let声明与if之间应插入一个空行。

缺陷七:单行过长

alert(Power ${n} is not supported, please enter an integer number greater than zero);这一行太长。主文在“行的长度”一节中指出:没有人喜欢读一长串代码,最好将代码分割一下。一行最大长度应由团队达成一致(通常是 80 或 120 个字符)。模板字符串(反引号`)天然支持跨行,因此可以把这条提示信息拆成两行:

alert(`Power ${n} is not supported, please enter an integer number greater than zero`);

主文中还给出了if条件过长时的拆行示范——把多个条件纵向排列,每个条件一行:

if ( id === 123 && moonPhase === 'Waning Gibbous' && zodiacSign === 'Libra' ) { letTheSorceryBegin(); }

缺陷八:else 单独占一行

else独占一行不如写成} else {。主文在花括号一节的示例(if (condition) { ... })以及风格备忘图中都体现了这一点:闭合花括号与else、下一个左花括号连写在一行上,整体结构更紧凑、块归属一目了然。

缺陷九:函数调用缺少空格与分号

alert(pow(x,n))存在两个问题:嵌套调用pow(x,n)内部没有空格(应为pow(x, n)),且语句末尾缺少分号。主文在“分号”一节中强调:每一个语句后面都应该有一个分号,即使它可以被跳过——因为在极少数情况下,JavaScript 的换行符不会被解释为分号,容易埋下隐患(详见 分号一节)。修复为:

alert( pow(x, n) );

修复后的完整版本

综合以上所有修正,solution.md 给出的参考答案如下:

function pow(x, n) { let result = 1; for (let i = 0; i < n; i++) { result *= x; } return result; } let x = prompt("x?", ""); let n = prompt("n?", ""); if (n <= 0) { alert(`Power ${n} is not supported, please enter an integer number greater than zero`); } else { alert( pow(x, n) ); }

对比前后两个版本可以看到:函数体内,变量初始化、循环逻辑、返回值之间用空行做了垂直分割;for循环体独占一行并缩进两个空格;if/else以} else {形式连接;所有运算符、逗号、括号前后都保留了规范的空格;每条语句都以分号结尾。功能完全不变,但可读性有了质的提升。这也是 代码风格主文 开头给出的规范示例风格(主文中n < 0版本的完整范本可参见该文“语法”一节)。

从“改对”到“写对”:支撑这些规则的原理

练习只要求修复一段代码,但真正重要的是理解每条规则背后的理由。结合 代码风格主文,可以把本练习涉及的规则归纳为几组:

花括号:选择哪种写法

主文对比了if的四种写法:

  1. if (n < 0) {alert(...)}—— 初学者常把花括号与语句挤在一行,非常不好;
  2. if (n < 0)换行后再写alert(...)、不加花括号 —— 永远不要这样做,添加新行很容易出错;
  3. if (n < 0) alert(...)单行无花括号 —— 如果代码很短,可以接受;
  4. if (n < 0) { ... }——最好的方式。

本练习中的if (n<=0)恰好属于第 1 类的变形(花括号另起一行),应改为第 4 类写法。对于极短语句(如if (cond) return null),单行写法也是可接受的,但块结构通常更具可读性。

缩进:水平与垂直两个维度

  • 水平缩进:通常为 2 或 4 个空格(或 Tab)。如今空格更普遍,因为空格可以比 Tab 做出更灵活的缩进配置(例如把函数参数与左括号对齐)。本练习统一采用 2 空格缩进。
  • 垂直缩进:用空行把代码拆分成逻辑块。本练习在result初始化、for循环、return之间,以及let声明与if之间插入空行,正是这一原则的体现。

嵌套层级:尽量浅

主文建议尽量避免过深嵌套,例如循环内不要层层加if,可以用continue提前跳出:

for (let i = 0; i < 10; i++) { if (!cond) continue; ... // <- 没有额外的嵌套 }

if/else与return的组合也可以达到同样效果:把“特殊情况”在一开始就处理掉(例如n < 0时直接return),主代码流就不需要额外嵌套。本练习的pow函数虽然嵌套不深,但else分支的写法同样可以套用这一思路——条件不满足时立即结束,主体逻辑平铺展开。

函数位置:先调用、后定义

主文指出,如果代码中有“辅助函数”与调用它们的代码,组织方式有三种:函数在上、调用在下;调用在上、函数在下;混合式。大多数情况下“先写调用代码、再写函数”更好,因为阅读时我们首先想知道的是“它做了什么”。本练习中pow先定义后调用,属于第 1 种方式,在课堂练习中完全合理;但在真实项目中,把“做什么”的调用代码放在前面往往更利于他人快速理解程序主干。

把规则自动化:风格指南与检查器(Linters)

人工逐行审查难免遗漏,团队协作时更需要统一标准。主文介绍了两类工具化手段:

风格指南

风格指南是“如何编写代码”的通用规则集,涵盖用哪个引号、缩进几个空格、一行最大长度等细节。当团队所有成员遵循同一份指南时,无论代码由谁编写,风格都是统一的。业界已有多种成熟方案可供选择(如 Google、Airbnb、Idiomatic.JS、StandardJS 等),初学者可以从本文这类基础规则起步,再挑选自己偏好的指南。

ESLint 等自动检查器

检查器(Linters)可以自动检查代码风格并提出改进建议,而且顺带能发现变量或函数名拼写错误等真实 bug——因此即使不打算固守某种风格,也建议安装一个。主文提到 JSLint、JSHint、ESLint 等工具,并给出了 ESLint 的启用流程:

  1. 安装 Node.js;
  2. 使用npm install -g eslint安装 ESLint;
  3. 在项目根目录创建.eslintrc配置文件;
  4. 在编辑器中安装/启用 ESLint 插件。

主文给出的.eslintrc示例:

{ "extends": "eslint:recommended", "env": { "browser": true, "node": true, "es6": true }, "rules": { "no-console": 0, "indent": 2 } }

其中"extends": "eslint:recommended"表示基于 ESLint 的推荐规则集进行设置,然后通过"rules"覆盖或追加自定义规则——例如示例中把缩进规则设定为 2 空格("indent": 2),与本练习采用的缩进风格完全一致。把本练习中发现的“缺陷类型”(空格缺失、分号缺失、花括号位置、行过长等)交给检查器自动把关,正是“从人工修复到机器预防”的最佳实践路径。

总结:一份可复用的代码风格自查清单

回到本练习,把 solution.md 揭示的九类问题整理成清单,即可作为日常自查的速查表:

  1. 参数与括号:函数名与(之间、参数之间、嵌套调用参数之间都要有空格;
  2. 花括号位置:左花括号与关键词同行(K&R 风格),} else {连写在一行;
  3. 运算符空格:=、<=、*=等运算符两侧保留空格;
  4. 控制结构:for、if、while后留空格,循环体内容换行、缩进;
  5. 变量声明:每行一个变量,使用let x = ...;完整写法并加结尾分号;
  6. 空行分割:不同逻辑块之间用空行做垂直分割;
  7. 行长度:超过团队约定(通常 80/120 字符)时拆分,模板字符串可跨行;
  8. 分号:每条语句末尾都写分号;
  9. 嵌套深度:用continue、提前return减少嵌套层级。

主文在“总结”一节给出的判断标准值得反复体会:当我们思考如何写“更好”的代码时,应该问自己两个问题——“什么可以让代码可读性更高、更容易被理解?”以及“什么可以帮助我们避免错误?”本练习的每一处修复,最终都服务于这两个目标。

  • 文档
  • 教程
  • 前端

【免费下载链接】zh.javascript.info

现代 JavaScript 教程(The Modern JavaScript Tutorial),以最新的 ECMAScript 规范为基准,通过简单但足够详细的内容,为你讲解从基础到高阶的 JavaScript 相关知识。

项目地址:https://gitcode.com/gh_mirrors/zh/zh.javascript.info
点击查看免费下载

相关推荐

上一篇:3分钟极速部署:为华硕路由器打造全网广告拦截系统
下一篇:如何安装 Mac Mouse Fix:为 Mac 鼠标选对安装方式并设置平滑滚动的完整指南

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

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

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

立即咨询