前言
代码排版是编程中非常重要的一环,它直接影响到代码的可读性和维护性。整洁优雅的代码就如同优雅的设计一样让人心旷神怡,做好排版能使团队中小伙伴在阅读我们写的代码时至少能停留3秒,不至于辣眼睛被嫌弃,让阅读的人一眼能看出这个函数在做什么,有几个逻辑块,有几个阻塞(return)。本文将以JavaScript作为演示语言,利用 排版、语法糖、注释 做为基石,以此来协助我们提高编码效率,提升编码幸福感,疯狂取悦自己。
排版
变量与常量分组定义
// 先定义常量,再定义变量
const var1 = bar();
const var2 = 2;
const var3 = foo();
let var4 = 4;
let var5 = foo();
let var6 = 6;
逻辑块的分组
变量要与邻近逻辑关联,逻辑块中的变量与常量集中到逻辑块顶部,一个函数中建议不要超过3个逻辑块,超出则拆分为多个函数
// 逻辑块1
const var1 = bar();
const var2 = 2;
let var4 = 4;
let var5 = foo();
for (let i = 0; i <= 100; i++) {
// do var1 var2
}
for (let i = 0; i <= 100; i++) {
// do var4 var5
}
// 逻辑块2
const var6 = bar();
const var7 = 2;
let var8 = 4;
let var9 = foo();
for (let j = 0; j <= 100; j++) {
// do var6...
}
// 逻辑块3
const var10 = bar();
const var11 = 11;
let var12 = 12;
let var13 = foo();
for (let k = 0; k <= 100; k++) {
// do var10...
}
合理的使用空行
仅有一个逻辑块时,变量组与常量组之间可以适当添加空行(分隔行)
// 常量组与变量组之间使用了空行
const var1 = bar();
const var2 = 2;
const var3 = foo();
let var4 = 4;
let var5 = foo();
let var6 = 6;
for (let i = 0; i <= 100; i++) {
// do
}
for (let i = 0; i <= 100; i++) {
// do
}
逻辑块中存在 return 时分隔行与变量分组的处理
// 先定义 return 前需要的相关变量
const var1 = 1;
let var2 = foo():boolean;
for (let i = 0; i <= 100; i++) {
// do var2
}
if(!var2){
return;
}
// 逻辑被停止执行时可适当换行
// 逻辑块2
const var3 = foo();
let var4 = 4;
let var5 = foo();
let var6 = 6;
// 变量组与下方代码可适当换行
for (let i = 0; i <= 100; i++) {
// do
}
for (let i = 0; i <= 100; i++) {
// do
}
使用解构
推荐的
const { var1, var2, var3 } = object1;
let var4 = 4;
不建议
const var1 = object1.var1;
const var2 = object1.var2;
const var3 = object1.var3;
let var4 = 4;
分号(😉
神学信仰:分号YYDS
科学说法:不使用分号可能会导致某些未知的错误
花括号的位置
在大多数编程语言中,花括号的位置有多种约定,例如K&R风格(花括号在控制结构声明同一行的末尾)和Allman风格(花括号另起一行)。选择一种并保持一致性。
语法糖
逻辑操作符 (&&)
const var1 = false;
// 不使用 && 的两种形式
if(var1) foo();
if(var1) {
foo();
}
// 使用 &&
var1 && foo();
判断逻辑简单使用switch代替多个else if
const type = 1;
switch(type) {
case 1:
// do
break;
case 2:
case 3:
// do
break;
default:
// do
}
判断逻辑复杂使用函数代替多个else if
const type = 1;
const isOne = (param, other):boolean => {
return param === 1;
}
const isTwo = (param):boolean => {
return param === 2;
}
const isThree = (param):boolean => {
return param === 3;
}
isOne(type) && do1();
isTwo(type) && do2();
isThree(type) && do3();
双问号 (??) 或运算(||)
const var1 = 0;
const var2 = null;
const var3 = undefined;
const var4 = false;
const var5 = '';
/**
* - 双问号仅左侧值为 null 与 undefined 时,返回左侧值
* - 适用于变量为0或空值且不作为布尔判断的情况
*/
var1 ?? false; // 0
var2 ?? true; // true
var3 ?? true; // true
var4 ?? true; // false
var5 ?? false; // ''
/**
* - 在或预算中 0、null、undefined、false、'' 均做假值运算
* - 用或预算常见BUG则是0需要作为有效值时被当做假值
*/
var1 || false; // false
var2 || true; // true
var3 || true; // true
var4 || true; // false
var5 || false; // false
反引号 (`)
推荐的
const color = '#f00';
const size = '14';
const unit = 'pt';
const family = 'Arial';
const font = `${color ?? '#ccc'} ${size}${unit} ${family}`;
不建议
const color = '#f00';
const size = '14';
const unit = 'pt';
const family = 'Arial';
// 可能会存在一些数据类型隐式转换错误的问题
const font = color + size + unit + family;
注释
适当地添加注释来解释代码的目的、算法、特殊情况等。注释应该清晰、简洁,并与代码保持同步。
属性与变量注释
/**
* 中文注释
* @val val1
*/
let val1 = 0;
/**
* 中文注释
* @val obj1
*/
const obj1 = {
/**
* 名称
* @val name
*/
name: '',
/**
* 年龄
* @val age
*/
age: 18,
}
复杂逻辑注释
/**
* 当前逻辑块的概述
* - 这里是详细说明1
* - 这里是详细说明2
*/
for (let i = 0; i <= 100; i++) {
// do
}
函数/方法注释
/**
* @description: 构造函数
* @param {Spreadsheet} context 表格实例
* @param {ObjectMatrix<ICellDataCache>} cellMatrixCache 单元格渲染数据
* @param {CellMatrixCacheCreatedEvent} event 事件 - 单元格渲染数据创建完成后
*/
constructor(
context: Spreadsheet,
cellMatrixCache?: ObjectMatrix<ICellDataCache>,
event?: CellMatrixCacheCreatedEvent
) {
// do
}
结语
由于篇幅原因,除上文中列出的一些排版方式之外,还有诸如缩进、命名规范和IDE工具插件等已成为事实约定的方式则没有在文中提到。
上述内容是个人在编码过程中总结的排版建议,如有谬误之处还请多多指出。