好的代码,注释肯定不能少,就目前而言基于 vue
的项目大部分都是使用的 vue2
,vue2
相对于 ts
的支持没有那么完善,大部分包括我目前工作所在的团队,使用的 vue
版本都是采用 vue2
并且不带 ts
支持,对于曾经用过或者习惯使用强类型的,难以离开 IDE
编码提示的人来说,这其实很难受,那么目前 vue2
项目可以通过 JSDoc
通过加注释的方式去过渡类型,配合 IDE
在某些情况能够达到使用 typescript
差不多的体验
最新版本更新了 JS 常见注释的写法和小细节
定义
关于 JSDoc
的相关定义可以参考这个链接,讲的挺多,甚至有很多用不上,可以考虑当成一本字典
用法
前端我用过的 IDE
时间比较长的只有 VS Code
和 Webstorm
,先不去纠结它们的好坏,它们对方法的注释都可以使用 JSDoc
,如下动图
常规
没有像 ts
那种环境的约束的话,还是很难让人有动力去写注释的,所以一般人写的注释都是写个 string/number/boolean
啥的,就是类似下面的情况
常用的就是这些,用来写下约束一下表单还是很好用的,还有数组之类的可以加上去尝试一下
二维数组也可以使用
可选参数
@param {type} [p]
可选参数@param {type=} p
可选参数
例子如下
/**
* demo
* @param {string} a
* @param {string} [b]
* @param {boolean=} c
*/
function foo(a, b, c) {}
效果如下
参数默认值
@param {type} [p=defaultValue]
参数默认值
例子如下
/**
* demo * @param {string} a
* @param {string} b
* @param {boolean} [c=false]
*/
function foo(a, b, c) {}
效果如下
PS: VS Code 对默认值的支持不够,效果如下
非常规
数组结构
当参数为数组时可以做到对其每个元素进行详细描述,格式如下
/**
* 数组参数:
* @param {array} arr 参数描述
* @param {string} arr[0] 参数描述
* @param {number} [arr[1]=undefined] 参数描述
*/
例子如下
/**
* demo
* @param {Array} arr
* @param {string} arr[0]
* @param {string} [arr[1]=123]
*/
function foo(arr) {}
效果如下
对于数组的注释,我个人感觉一般,不能达到 TS
的效果,不建议对数组参数里面的每个索引值进行描述,有可能会引发歧义
对象结构
暂时没有找到一个很专业的名词来介绍这部分,姑且就用它的使用范围来介绍,对象结构就是,某个参数可能是一个固定的结构的对象,类似于
{
name: 'steven',
age: 21
}
像这种情况,注释可以这样写
/**
* demo
* @param {{name: string, age: number}} a
* @returns {number}
*/
function foo(a) {
return 2;
}
还算不错的提示
用在返回上面也是很方便的
但是 JSDoc
到了这一步,格式化就没有很方便了,并不会对其中的结构体做特定的格式化(包括 WebStorm
),这也算是很少有人去写这方面注释的一个原因,没有规范的定时炸弹,如果能出一个插件去补全这块,说不定可以激发前端程序员在非 ts
项目写上两句注释的动力
函数/方法注释
如果你的方法参数是 Object
形式,像上面的写法,会让维护者不解其中的意思,如下
/**
* demo
* @param {{name: string, age: number}} a
* @returns {number}
*/
function foo(a) {
return 2;
}
// name 是什么的名字呢?
所以可以采用另一种描述 Object
中各项的描述,如下
/**
* demo
* @param {Object} a
* @param {string} a.name 回复人的名字
* @param {number} a.age 回复人的年龄
* @returns {number}
*/
function foo(a) {
return 2;
}
WebStorm 效果
可以看到注释和类型,非常的不错
VS Code
同样的代码在 VS Code
上是这样的
并没有对应的属性注释,如果是下面这种写法就可以了
/**
* demo
* @param {{name: string, age: number}} a
* @param {string} a.name 回复人的名字
* @param {number} a.age 回复人的年龄
* @returns {number}
*/
function foo(a) {
return 2;
}
foo({ name: "张三", age: 22 });
但这样就有点麻烦了,我建议采用在 WebStorm
的写法,在 VS Code
编码时,就采用跳转的方式查看注释,类似下面这种效果
使用
Object
作为参数,一般用在配置项的场景
- 有些函数的参数并不是作为算法的输入,而是对算法的某些分支条件判断之用,比如
Boolean
值
function fun(node, isShow, isRed = false, data) {/* ... */};
// 调用时
fun(element, true, false, "123");
// 即使有默认值的存在仍然无法跳过 isRed
// 用配置项就可以解决这个问题
function fun(option) {
const {node, isShow, isRed = false, data} = option;
}
// 调用时
fun({node: element, isShow: true, data: "123"})
- 对于一些硬编码或者枚举值参数可以解释它的具体意思,如上例子
方法重载,比如上面那个例子,我既想用
fun(node)
又想用fun(data)
,isShow/isRed
可能是可选参数,使用配置型参数设计就可以解决fun({node: element}) | fun({data: '123'})
更多关于参数的设计,请参考JavaScript编码规范 - 3.8.2 参数设计
自定义类型
有些时候我们可能需要使用复用一些结构体,可以使用 JSDoc
封装,如下
/**
* 包含姓名和年龄的对象
* @typedef {Object} Person
* @property {string} name - 姓名
* @property {number} age - 年龄
*/
/**
* @type {Person} person
*/
const person = {
name: 'steven',
age: 21
}
跨文件使用
// ./@types/index
/**
* 包含姓名和年龄的对象
* @typedef {Object} Person
* @property {string} name - 姓名
* @property {number} age - 年龄
*/
/**
* @type {Person} Person
*/
// ./t.js
/**
* @typedef {import('./@types/index').Person}
*/
/**
* demo
* @param {Person} a
* @returns
*/
function foo(a) {
return 2;
}
Vs Code
在这块的注释方面就比不上 WebStorm
了
JSDoc
在复用这方面,就不如 typescript
好用了,说实话,如果你的项目都需要用到这种类型了,应该尽快考虑是否应该使用 typescript
,JSDoc
的生态方面还是比不过 typescript
的,而且两者写法差距蛮大,一旦写得多了,调头比较难
接口
接口 API
的注释还是挺重要的,如果 JSDoc
能用在这上面还是挺方便的,其示例如下
/**
* demo
* @returns {Promise<{data:{name: string, age: number}}>}
*/
function foo() {
return new Promise((resolve, reject) => {
resolve({ data: { name: "steven", age: 21 } });
});
}
效果还行
总结
偶尔使用 JSDoc
写点简单的注释还行,但是复杂的项目和类型,JSDoc
和它的生态未必能够撑得住