在项目中关于 [代码质量] 的一点点总结

前言

不知不觉,已经工作接近5年了,项目大大小小也做了不少,虽然每个项目自己都是深度参与,但当我回看以前的代码时,还是会惊呼 [😲这是啥意思?是我写的吗?怎么看不懂], 于是开始关注自己的代码质量,今天把我这几年对于代码质量的心得做一个总结

好的代码就像一份好的报纸📰,题目就是整篇内容的缩写,而且内容要凝练清晰,上下逻辑联系紧密,不可拖拖拉拉,含糊不清,让人不知所云

命名

计算机科学中只有两个难题:缓存失效 和 命名 --Phil Karlton

函数命名

命名要偏向功能 ,而非执行过程,可以使用 前缀词 + [名词] + [动词]

前缀词部分总结:

说明 前缀词 举例
是否符合状态 is isDialogOpen
能否执行 can canUserActive
是否包含 has/include/contains containsUserId
是否需要 should / need needUsernameLogin
过滤 filter filterByName
合并 merge mergeConfig
排序 sort sortByAmount
转化 to/convert toUppderCase
从对象/数据结构中获取数据 get getUserId
计算获取数据 cal calUserAveragScore
网络请求 fetch fetchUserInfo
计算获取数据 cal calUserAveragScore
解析数据,不能直接获取 parse parseUserInfo
格式化 format formatDate
切换 toggle toggleSelected
新增 add addTag
创建 create CreateInstance
修改 update updateTag
删除 delete deleteTagById
移除 remove removeTagById

add 是表示新增,比如对于一个文章来说,可以使用 addTag 往这个文章中新增一个标签

create 是创建实例,常用于实例化方法和工厂方法的命名

delete 在于删除数据,是不可恢复的,比如在列表中删除一个子项(虽然后端是逻辑删除,但是对于前端来说是不可恢复

remove 是移除,比如给一个文章添加标签,这个标签可以移除掉,但是这个标签可以给其他文章使用

解释性变量 / 中间变量

一些变量是 只在函数中间使用, 但是有实际意义,避免过长的计算过程导致的心智负担

比如下面的这行代码,知道在干什么吗?🧞

js 复制代码
let orderInfo = {
    quanity:150,
    price:3.7
}

function getTotalPrice (orderInfo) {
  return orderInfo.quanity * orderInfo.price 
   -  Math.max(0, orderInfo.quanity - 100 ) *  orderInfo.price * 0.1
}

如果我们写成下面这样,是不是更加清晰了呢?

js 复制代码
// 总价格为商品总价(单价 * 数量) - 折扣(超过 100 个打 9 折)
let orderInfo = {
    quanity:150,
    price:3.7
}

function getTotalPrice (orderInfo) {
  // 基础金额
	let baseSumMoney = orderInfo.quanity * orderInfo.price;
  // 打折金额
	let discountMoney = Math.max( 0, orderInfo.quanity - 100 ) * orderInfo.price * 0.1;
	return baseSumMoney - discountMoney
}

baseSumMoneydiscountMoney 都属于 解释型变量

解释型变量大大提高了可读性,比如我们也可以在循环中使用

js 复制代码
  fruits.map(f=> doSomeing(f))

如果这个 循环代码量特别多,是不是停下来思考一下这个 f 是什么意思

如果我们改为下面这种,会不会好些呢?

js 复制代码
  fruits.map(fruit=> doSomeing(fruit))

还有就是 ts 中的 boolean 值的命名,你也许会写出下面的ts类型,只知道会是一个带 boolean 的 Promise, 但是不知道 boolean 是指代的什么

ts 复制代码
type UserInfo = Promise<boolean>

如果我们把 boolean 用一个有意义的变量来命名,是不是会变得更清晰⚔️

ts 复制代码
type CanActive = boolean;

type UserInfo = Promise<CanActive>

带单位的变量

比如有这样的一个节流函数

js 复制代码
function throttle(
          fn,
          delay // 无法确定 delay 是什么单位
        ){}

看不出 delay 可以传递什么,是 [ 毫秒 ] 还是 [ 秒 ] 呢?

js 复制代码
function throttle(
          fn,
          delaySeconds
        ){}

这样写是不是就知道要传什么了吧

数字

一些能够描述 数字意义 的词语,可以使用驼峰命名 比如: min,max,total 等等

js 复制代码
const minBugs = 1
const maxBugs = 5;
const totalBugs = 3
const numberOfStudents = 20;

有时也要根据上下文使用合适的单位🎁

js 复制代码
let minuteCount = 120;
let distanceInMeters = 500;

常量

使用 const 并且全部大写,命名只能使用下划线

js 复制代码
cosnt PI = 3.14;

函数

函数的命名在前面已经说过了,接下来是函数的其他方面

尽量使用 纯函数,使用纯函数的好处就不多说了,说一个比较坑的例子

js 复制代码
let obj = {
  name:"lisi"
}

function a(obj){
  obj.name = 'zs'
}

a(obj)

猜猜现在 obj.namezs 还是 lisi?

zs!!

对于引用传递要当心💔

函数的要点

  1. 函数的形参数量要少于 3 个,否则可以使用对象形式传递

如果形参过多,对调用者就会造成很大的心智负担

  1. 函数要么做事,要么回答问题

是函数拆分的重要依据,如果无法精确的起一个函数名的话,说明可以再拆分

  1. 函数无副作用,不影响外部变量 比如添加一个 item
js 复制代码
const addItemToCart =(cart,item)=>{
    return [...cart,{item}]
}

代码格式

  1. 应该像读报纸,顶部给出高级的算法和概念,细节依次展开
  2. 所有的变量统一写到最上面
  3. 代码组之间添加空白行

比如

js 复制代码
function Clone() {
  var clone,copy,
      i = 1,
      target = arguments[0] || {},
      length = arguments.length;

  if (typeof target === "boolean") {
    target = arguments[1] || {};
  }

  for (; i < length; i++) {
    if((options = arguments[ i ] ) !== null)
      for (name in options) {
        copy = options[ name ]

        if (typeof copy == "object"){
          clone = {}
          Clone(clone, copy)
        } else {
          target[ name ] = copy;
        }
    }
  }

  return target
}

总之代码要整洁大气

注释

如果可以使用变量名来解释,就不要使用注释

如果非要使用注释,可以使用 jsDoc来提供更多信息

param

你可以在变量说明前加个连字符,使之更加容易阅读

js 复制代码
/**
 * @param {string} somebody - Somebody's name.
 */
function sayHello(somebody) {
  alert('Hello ' + somebody);
}

可选参数

js 复制代码
/**
 * @param {string} [somebody] - Somebody's name.
 */
function sayHello(somebody) {
    if (!somebody) {
        somebody = 'John Doe';
    }
    alert('Hello ' + somebody);
}

默认参数

js 复制代码
  /**
 * @param {string} [somebody=John Doe] - Somebody's name.
 */
function sayHello(somebody) {
    if (!somebody) {
        somebody = 'John Doe';
    }
    alert('Hello ' + somebody);
}

联合类型

js 复制代码
 /**
  * @param {'GET' | 'POST'} method 请求方法
  */
 function m( method ){}

数组对象

js 复制代码
/**
 * Assign the project to a list of employees.
 * @param {Array.<{ name: string, department: string }>} employees - The employees
 */
function assignProjectToEmployees(employees) {
  // ...
}

普通对象

js 复制代码
/**
 * Assign the project to an employee.
 * @param {Object} employee - The employee who is responsible for the project.
 * @param {string} employee.name - The name of the employee.
 * @param {string} employee.department - The employee's department.
 */
function Project  (employee) {
  // ...
}

@example

对函数的使用进行举例说明

js 复制代码
/**
* @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 */

ts中可以使用md语法做注释

ts 复制代码
/**
*
@description ### 填充模式
- stretch 拉伸充满
- cover 裁切充满,保持图片比例
- contain 全部显示,留白,保持图片比例 */ 
type mode = "stretch" | "cover" | "contain";

结束

现在只想到这么多,如果以后有什么新的心得,还会继续更新⚓⚓⚓

相关推荐
Mintopia1 分钟前
计算机图形学中的几何体布尔运算:一场形状的奇幻冒险
前端·javascript·计算机图形学
Mintopia6 分钟前
Three.js 动态加载 GLTF 模型:高效加载和渲染复杂的 3D 模型
前端·javascript·three.js
std78797 分钟前
VITA STANDARDS LIST,VITA 最新标准清单大全下载_ansi vita 2025
java·前端·javascript
不怎么爱学习的dan7 分钟前
使用原生 JavaScript 实现组件化开发
前端
CAD老兵8 分钟前
条件类型(Conditional Types)
前端
VincentFHR8 分钟前
Shader 蜂窝网格扩散动画
前端
CAD老兵9 分钟前
深入理解 JavaScript 和 TypeScript 中的 `BigInt` 类型及其 Polyfill 方法
前端
wen's9 分钟前
React Native 弹窗组件优化实战:解决 Modal 闪烁与动画卡顿问题
javascript·react native·react.js
Z_haha9 分钟前
Vite HMR API 详解
前端·vite
rookiefishs10 分钟前
如何控制electron的应用在指定的分屏上打开🧐
前端·javascript·electron