在必要的地方加注释
良好的注释可以帮助开发人员理解代码的逻辑、功能和实现方式,减少维护成本,提高代码质量和可维护性。
以下是一些前端代码注释的最佳实践:
- 注释清晰明了:注释应该简洁明了,用简单易懂的语言解释代码的逻辑和功能。避免过度使用注释,以免使代码变得冗余和难以阅读;
- 声明代码的意图,准确地描述函数的行为;
- 对参数和返回值注释,入参代表什么,出参代表什么;
- 用输入/输出的例子来说明特别的情况;
- 当代码还未完成时可以使用 todo 注释来注释;
- 使用统一的风格;
可以在vscode的插件市场,下载koroFileHeader 进行安装,可以一键生成注释格式。
统一的代码风格
统一的前端代码风格规范可以使前端开发更加高效和易于维护。通过遵循一致的缩进和空格、行宽限制、语句结束符、语句块、命名规则、注释、文件命名、模块化和组件化等规范,可以使前端开发更加规范化、易于阅读和维护。同时,使用代码质量检查工具(如ESLint)也可以帮助团队发现和修复代码中的问题,提高代码质量。
以下是一些统一前端代码风格规范的最佳实践:
- 命名规范:使用有意义的变量和函数命名,遵循驼峰命名法或下划线命名法,以便于阅读和理解代码。
一般常见的命名规范如下:
- 变量:小驼峰,使用有意义的英文命名,如newsDetail
- 函数:小驼峰,应该采用动词+名词的形式,如getNewsDetail
- 类名:大驼峰,如EventBus
- 常量:大写+下划线分割,如NEWS_STATUS
- 目录:小写+中划线分割,如file-name
- 文件:小写+中划线分割,如 event-bus.js,团队内部统一即可
- 组件:组件名应该始终使用首字母大写的驼峰命名法
- 代码缩进:使用一致的代码缩进,通常是两个或四个空格,以提高代码的可读性。
- 行宽:限制代码行的长度,通常不超过80个字符。
- 括号位置:统一括号的位置,例如将所有括号放在行首还是行尾。
- 字符串引号使用单引号
- 循环判断不能超过三层
函数篇
在编程中,函数是我们进行模块化、复用代码的重要工具。保持函数的整洁和可读性对于代码的可维护性和可扩展性至关重要。以下是一些关于如何保持函数整洁的最佳实践:
- 函数应该短小精悍:一个函数应该只做一件事,并且这件事应该在函数名中明确表达出来。如果一个函数开始变得过于复杂或过长(一般来说,不超过80行),那么可能就是时候考虑将其分解为更小的函数了。
- 避免重复:避免在多个函数中重复相同的代码。如果你发现自己在多个地方重复相同的代码,那么可能就应该将那部分代码提取出来,创建一个新的函数。
- 使用描述性的名称:函数的名称应该清楚地描述函数的功能。名称应该简洁明了,不要使用缩写,除非这个缩写是广泛使用的。
- 参数列表应该简洁:参数列表不应该过长。如果参数列表过长,那么可能就是时候考虑将某些参数封装到对象中,或者尝试使用其他设计模式来简化接口。
- 尽量减少全局变量的使用:全局变量可能会使得代码难以理解和维护。如果可能的话,尽量使用局部变量。
- 注释要恰当:注释应该是代码的补充,而不是替代。如果代码本身已经足够清晰,那么可能就不需要注释。在复杂的代码段前加上注释可以帮助阅读者理解代码的目的和工作方式。
- 函数应该是“纯”的:纯函数是一种函数,给定相同的输入,总是返回相同的输出,并且没有副作用。这种类型的函数通常更容易测试和理解。
- 错误处理:每个函数都应该能够处理错误,而不是让错误传播到调用堆栈的顶部。每个函数都应该有一个明确定义的错误处理策略。
符合阅读习惯
写代码也是一个表达的过程,虽然表现形式不同,但是如果我们能够采用符合人类自然语言习惯的表达习惯来写代码,对阅读代码的人理解我们的代码是很有帮助的。
条件语句中的正负逻辑
在判断一些正负逻辑的时候,建议使用if(result)而不是if(!result)。
if/else语句块的顺序
在写if/else语句的时候,可能会有很多不同的互斥情况(好多个elseif)。那么这些互斥的情况可以遵循哪些顺序呢?
- 先处理掉简单的情况,后处理复杂的情况:这样有助于阅读代码的人循序渐进地地理解你的逻辑,而不是一开始就吃掉一个胖子,耗费不少精力。
- 先处理特殊或者可疑的情况,后处理正常的情况:这样有助于阅读代码的人会马上看到当前逻辑的边界条件以及需要注意的地方。
使用return提前返回
在一个函数或是方法里,可能有一些情况是比较特殊或者极端的,对结果的产生影响很大(甚至是终止继续进行)。如果存在这些情况,我们应该把他们写在前面,用return来提前返回(或者返回需要返回的返回值)。
这样做的好处是可以减少if/else语句的嵌套,也可以明确体现出:“哪些情况是引起异常的”。
以字面常量取代魔法数
对于魔法数,应该用一个枚举对象或一个常量来赋予其可见的意义。这样,你在用到的时候,就能够明确的知道它代表的是什么意思
而且,当需求变化的时候,只需要改变一个地方即
const LOGIN_SUCCESS = '3756'; // 为业务常量命个名,看起来就非常清晰易读
if (res.code === LOGIN_SUCCESS) {
// todos
}
简化逻辑
使用函数或者方法
将复杂的逻辑块封装到单独的函数或者方法中。这不仅可以使你的主程序更加简洁,还可以使你的代码更加模块化,易于维护和测试。
// not-recommended ❌
// 下面这个if里面的判断条件,需要花一番精力才能知道作者要表达的是什么;
let getPrice = function( price ){
let date = new Date();
if ( date.getMonth() >= 6 && date.getMonth() <= 9 ){ // 夏天
return price * 0.8;
}
return price;
};
// recommended ✅
// 提炼成单独的函数就能做到一目了然了;
let isSummer = function(){
let date = new Date();
return date.getMonth() >= 6 && date.getMonth() <= 9;
};
let getPrice = function( price ){
if (isSummer() ){ // 夏天
return price * 0.8;
}
return price;
};
减少if...else面条代码
为完成一个功能每个程序员都会有不同的算法或者说写法,通常来说越清晰的算法可维护性越高。当发现做一件事可以有更清晰的方式,你就就应该用比较清晰的方式取代复杂的方式。
function foundPerson(people) {
for(let i = 0; i < people.length; i++) {
if (people[i] === "Don") {
return "Don";
}
if (people[i] === "John") {
return "John";
}
if (people[i] === "Kent") {
return "Kent";
}
}
return "";
}
我们其实并不需要这些条件语句:
function foundPerson(people) {
const candidates = ["Don", "John", "Kent"];
return people.find(p => candidates.includes(p)) || '';
}
switch代替多个if else
function commandHandle(command){
if(command === 'install'){
install()
}else if(command === 'start'){
start()
}else if(command === 'restart'){
restart()
}else{
showToast('未知命令')
}
}
switch比较适合这种判断条件比较单一的情况,如判断是否等于某个字符串或者数字,如果if条件存在3个及以上,使用switch相对来说结构更加清晰。
function commandHandle(command){
switch (command){
case 'install':
install();
break;
case 'start':
start();
break;
case 'restart':
restart();
break
default:{
showToast('未知命令')
}
}
}
还可以进行更进一步的优化,通过一个map来指定每个命令对应的动作。
可以利用策略模式来做进一层的优化
function commandHandle(command) {
let commandHandleMap = {
install,
start,
restart,
default: () => showToast('未知命令')
}
let handle = commandHandleMap[command] || commandHandleMap['default']
handle()
}
卫语句取代嵌套条件表达式
如果某个条件极其罕见,就应该单独检查该条件,并在该条件为真时立刻从函数中返回。这样的单独检查常常被称为“卫语句
function getPayAmount() {
let result;
if (isDead)
result = deadAmount();
else {
if (isSeparated)
result = separatedAmount();
else {
if (isRetired)
result = retiredAmount();
else
result = normalPayAmount();
}
}
return result;
}
使用卫语句可以大大减少嵌套语句的数量,增强可读性:
function getPayAmount() {
if (isDead) return deadAmount();
if (isSeparated) return separatedAmount();
if (isRetired) return retiredAmount();
return normalPayAmount();
}