【如诗般写代码】你甚至连注释都没玩明白
引言
要问我认为最难的事是什么,那只有维护前人的代码。
我经常能看见一个文件里,写上百行,没有几个函数,没有注释,没有换行,
一头扎进去,闷头写到天昏地暗的
什么修复bug
,提升性能之类的都不是事,会用调试工具和分时渲染就够了
但是看屎山是真的难受
注释篇
- 利用注释在编辑器开启代码提示
看到区别了吗,左边用的是文档注释,鼠标悬浮能看到变量描述
右边用的是行内注释,没有任何作用初步认识了文档注释的好处后,很多人可能还是不用,因为嫌麻烦。
所以编辑器也为你着想了,以 VSCode为例,输入/**
,就会自动生成文档注释
如果在函数上面,再按下回车,还能补齐函数参数文档,如下图所示
- 利用文档注释描述函数功能
当我鼠标悬浮在函数上时,就能看到他的各种描述,从其他文件导入也有效
- 智能提示当前参数描述,以及类型等
这里也能用快捷键呼出,详见我上篇文章:# 【最高效编码指南】也许你不会用VSCode | IDEA
- 添加 JS 类型,实现类似 TS 的效果
这里我呼出代码提示,但是他并没有给我补全任何方法,因为他不知道你的类型是什么
如果是强类型语言的话,那就会给你补全代码
那么动态类型如何实现呢?以 JS 为例,使用文档注释即可,也就是前阵子沸沸扬扬的利用 JSDoc 代替 TS不仅于此,连枚举都能实现,反正 TS 有的,他应该都有,我没有详细研究
- 文档注释指令
如下图所示,我想在文档注释里写上用法,但是他的格式十分丑陋,而且没有语法高亮
于是我使用 example 指令,告诉他这是一个示例,这时就有语法高亮了
指令还有很多,你们输入 @ 就会有提示了,比如 deprecated,标记已弃用
这时你使用它就会有个提示,并且划上一根线 - MarkDown 文档注释
有时候,指令可能不够用,这时就可以使用 MarkDown 语法了
- 结合 TS
定义类型时,写上文档注释,当你鼠标悬浮时,就能查看对应注释
函数重载情况下,文档注释要写在类型上才行,下面这种无效
要写在类型定义的地方才行
- 总结
如果你用的是变量、函数或是 TS 定义类型,你要写注释,那就一定要写 文档注释,我跪下来求求你了 😭
减少条件分支语句
- 策略模式,写个映射表即可。这个有一点开发经验的应该都知道吧
如果遇到复杂情况,映射表里也可以写函数,执行后返回逻辑
- 提前返回
这里第 2 种提前返回就减少了一层嵌套,实际开发中,能减少更多嵌套语句
- 多个相等判断,使用数组代替
代码七宗罪
让我来细数一下这坨代码的罪行,然后引出另一个主题,美化代码
下面这段,这简直是"甲级战犯",
- 一堆变量写了或者导入了不用,放那恶心谁呢
- 注释了的代码不删 (虽然可能有用,但是真丑)
- 都什么年代了,还在用
var
(坏处下面说) - 用行内注释和没写区别不大,要写就写文档注释 (文档注释的优点上面解释了,不再赘述)
- 小学生流水账一般的代码,连个函数入口都没提供,想一句写一句
- 连个代码格式化都不会,多按几个回车,你的键盘不会烂掉;每个分段加个注释,你的速度慢不了多少
- 硬编码,所有类型用字符串直接区分,你万一要改怎么办?
语义化
我经常能看见一个文件里,写上百行,没有几个函数,没有注释,没有换行
一头扎进去,闷头写到天昏地暗的,比如下面这种
这玩意要我一行一行看?我是真的被恶心坏了
写代码要突出一个重点,看个大概,然后才能快速排查,看第三方库源码也是如此
我的习惯是写一个主入口,你叫 main | init | start 什么的都行,我只希望你能写上
然后主入口按照逻辑,给每个函数命名,这样一眼就能看出来你在干什么
如下图所示,这是我的偏好
我喜欢利用函数全局提升,把初始化函数放在文件顶部。这样每次打开一个文件,就能立刻看到大概逻辑
所以我很少用匿名函数,像上面那种全部写一坨,还都是匿名函数,我真的很难看出来谁是函数,谁是变量
这就引出一个新问题,函数的二义性
函数二义性
众所周知, JS 的类就是函数,里面有自己的 this,可以 new 一个函数
你要知道他是函数还是类,一般是通过首字母是否大写区分
但是这仅仅是弱规范,人家爱咋写咋写,所以后来出现了匿名函数(主要还是为了解决 this)
匿名函数没有自己的 this 指向,没有 arguments,如下图
而且用 const 定义,所以也就没了函数提升,严格来说,匿名函数才是真函数
不过我觉得直接写匿名函数有点丑,而且写起来似乎繁琐一点,虽然我都是用代码片段生成的
如果用了匿名函数,那么我就没了函数提升了
所以我仅仅在以下情况使用匿名函数
- 作为回调函数
- 不需要 this
- 函数重载
函数重载我来说说吧,应该挺多人不知道。
比如下图,针对每一种情况,写一遍类型,这样就能更加清楚描述函数的所有参数情况
不过这样好麻烦,而且好丑啊,于是可以用接口,这时你用 function 就实现不了了
var 的坏处
- var 会变量提升,你可能拿到 undefined
- var 没有块级作用域,会导致变量共享
按照常识,下面代码应该输出 0,1,2,3,4
但是你里面是异步打印,于是等你打印时,i 以及加了5次了,又没有块级作用域,所以你拿到的是同一个东西
在古时候,是用立即执行函数解决的,如下图。因为函数会把变量存起来传给内部
现在用 let 就行了
所以我求求你别用 var 了
格式化
这里可能有争议性,仅仅是我个人喜欢,看着舒服
大多数写前端的,基本人手一个 Prettier 插件自动格式化,再来个 EsLint
然后也懒得看配置,默认就是 2 格缩进,回车多了会被删掉什么的
这样下来,整个文件就相当臃肿,密密麻麻的,我看着很难受
我的风格如下
- 用 4 格缩进
- 代码按照语义类型分块,写上块级文档注释
- import 语句下面空两行,这样更加直观
- 每一段,用独特醒目的文档注释划分
- 定义变量优先使用 const,并且只写一个 const
- 函数参数过长,则一行放一个参数
- 写行内样式以及较长字符串时( 比如函数作为字符串 ),用特殊的宽松格式书写,保持类似代码的格式化
- if 分支语句,要多空一行,看着清爽
- 三目运算,用三行来写
- 条件判断尽量提前 return,减少分支缩进
下面来用图演示一下,不然看着上面的描述抽象
代码按照语义类型分块,写上块级文档注释
每一段逻辑写完,用个醒目的、大块的文档注释分开。
全部执行的逻辑,放在一个 init 函数中
定义变量优先使用 const,并且只写一个 const
比如声明变量,我喜欢这么写
按照分类,类型不同则换行,并且写上注释,仅用一个 const
来看看大众写法,可以说 99.9878987%的人都这么写,这种我一看就难受
如果你用 let,并且用 4 格缩进,那么你就刚好对齐了,能少写一个回车
不过尽量使用 const
函数参数过长,则一行放一个参数
如果你这么写,那我看完会头晕眼花,属实是又臭又长的参数列表
如果你这么写,我会夸你代码和人一样好看
三目运算格式化
这俩,你说谁的可读性高,肯定是分三行写的好看啊
字符串以及对象格式化
这俩,你说谁看得舒服,那肯定是 2 啊
我看了身边的人和网上的很多代码,大多数都是 1 这种
不管你是用字符串,还是对象等方式表达,你都应该写 2 这种样式
分支语句
这俩哪种好看还用说吗,肯定是左边的好啊。但是你用 Prettier 格式化的话,应该就变成右边的了
同理 try catch 之类的也是一样
最后,多用换行,我跪下来求求你了 😭
来源:juejin.cn/post/7335277377621639219