JSDoc 规范前端注释
概述
良好的注释是日常开发中的基础规范,注释能在维护项目时帮助开发人员快速了解上下文,节约开发时间,提高项目可维护性。然而,在项目维护的过程当中,随着项目维护的人员变多、代码的上下文变复杂,很容易出现注释风格不统一、注释内容较为随意的问题。显然,如果阅读注释再理解代码的时间大于直接阅读代码理解上下文的时间,注释也就失去了意义。
JSDoc 是一个基于 JavaScript 的文档生成工具,类似于 Javadoc 或 phpDocumentor,可以将文档注释直接添加到源代码中。也可以将 JSDoc 视为一套代码注释规范,其对开发中的常用概念进行了归纳,对格式做出了约定,具有较好的统一性和可读性。
除此之外,JSDoc 与主流 IDE 的结合也较好,通过 JSDoc 注释的模块或变量,当鼠标悬浮在变量上时即可显示出对应的说明内容;JSDoc 可以通过类型注释对没有使用 TypeScript 的项目进行类型约束,也许你已经听过“前端框架 Svelte 重构代码,反向迁移到 JavaScript”之类的前端资讯;另外 JSDoc 还能结合各种插件自动输出为 HTML 或 Markdown 格式的文档。
JSDoc 用法
基础用法
JSDoc 注释通常应该放在变量、函数或模块声明之前。为了被 JSDoc 解析器识别,每个注释必须以/**
序列开头。以/*
、/***
开头的注释将被忽略。
/** 有效的 JSDoc 注释 */
const a = 1
/**
* 有效的 JSDoc 注释
*/
const b = 1
// 无效的 JSDoc 注释
const c = 1
/* 无效的 JSDoc 注释 */
const d = 1
通过 JSDoc 注释的变量,鼠标光标悬浮在变量名上时会显示出注释的内容:
由于 JSDoc 在 VSCode 中采用的是 Markdown 渲染,所以 JSDoc 注释中也可以插入链接和图片。链接常用于说明当前需求的来源 Issue 或参考资料,图片使用的是当前文件相对于引用图片的相对路径。详细情况可以通过 VSCode 开源仓库的相关 Issue 了解。
/**
* 也可以插入链接、图片
* [链接](https://www.google.com/)
* 
*/
const a = 1
尽管绝大部分情况下不需要把注释做得如此复杂,但是 JSDoc 和 IDE 的集成确实拓展了常规纯文本注释的表达能力,在一些复杂、需要详细注释的场景下能够发挥作用。
标签
JSDoc 通过标签来规范注释的含义,并提供一些额外渲染内容。标签分为两种:
- 块标签:
@
开头,每个块标签至少一行。 - 内联标签:
@
开头,插入在一行的文本中,内联标签和内部文本必须用花括号括起来,可以在描述中或块标记中使用内联标签。
在下面的例子中,@param
是一个块标签,{@link}
是一个内联标签。
/**
* Set the shoe's color. Use {@link Shoe#setSize} to set the shoe size.
*
* @param {string} color - The shoe's color.
*/
Shoe.prototype.setColor = function(color) {
// ...
};
JSDoc 标准规范中定义了很多常用的块标签,详细内容将在下一节“标签类型”中说明。
类型标注
JSDoc 的主要应用场景之一就是可以在没有或者不使用 TypeScript 的情况下,为项目提供类型约束。
JSDoc 可以在变量声明时对变量的类型做出标记,如变量的类型,函数的参数、返回值、描述等。
/**
* Blend two colors together.
* @param {string} color1 - The first color, in hexidecimal format.
* @param {string} color2 - The second color, in hexidecimal format.
* @return {string} The blended color.
*/
export function blend(color1, color2) {}
// convert color to array of RGB values (0-255)
function rgbify(color) {}
export {
/**
* Get the red, green, and blue values of a color.
* @function
* @param {string} color - A color, in hexidecimal format.
* @returns {Array.<number>} An array of the red, green, and blue values,
* each ranging from 0 to 255.
*/
rgbify as toRgb
}
JSDoc 可以通过块标签引用外部模块,类似 TypeScript 中的 import type 或 interface。
/** A module. Its name is module:foo/bar.
* @module foo/bar
*/
/** The built in string object. Its name is external:String.
* @external String
*/
/** An event. Its name is module:foo/bar.event:MyEvent.
* @event module:foo/bar.event:MyEvent
*/
此外,JSDoc 也能描述 class、拓展 class、标注 module,对于 ES6、CommonJS、AMD Modules 等不同规范都有较好的支持。
以上所有的类型约束,在 js 文件开头加上// @ts-check
后,都能在 IDE 中得到类似 TypeScript 的实时类型检查。
尽管 JSDoc 能够在一定程度上起到 TypeScript 类型检查的作用,但是在 TypeScript 已经变为主流开发最佳实践的今天,大部分新项目应该在一开始就使用 TypeScript 进行开发或者直接使用 TypeScript 重构。可能只有使用 js 开发的大型老旧项目在渐进式重构的时候才需要大量使用 JSDoc 的类型注释功能吧。
标签类型
JSDoc 注释的语法简洁明了,但是标签的类型却非常多,文档中所规定的标准块标签有 60 个以上。当然实际使用中如果不进行类型标注,最常用的标签不超过五种,并且绝大部分标签仅仅只是文本含义上不同,IDE 都是作为纯文本展示。需要使用时再查阅文档即可。
以下根据笔者的个人理解对可能用到的标签做出简单的分类:
/** 最常用的 */
@type:描述变量的类型
@function:描述函数的功能、参数和返回值
@param:描述函数的参数及其类型
@returns:描述函数的返回值及其类型
@class:描述类的功能、属性和方法
@property:描述对象的属性及其类型
@interface:描述接口的功能和方法
@extends:描述类或接口的继承关系
@see:更多详细信息请参阅其他一些文档
@example:提供一个如何使用描述项的例子
@link:链接到文档中的另一个项目
/** 描述说明 */
@author:作者
@copyright:版权
@description:描述
@license:使用的许可协议
@file:描述一个文件
/** 继承相关 */
@abstract/@virtual:这个成员必须在继承类中实现或重写
@implements:标识实现一个接口
@access:指定该成员的访问级别
@augments:指明这个子类继承自哪个父类
@class:需要使用 new 关键字调用的构造函数
@constructs:这个函数作为类的构造实例
@interface:可以实现的接口
@override:覆盖其父类同名的标识符
/** 元素间关系 */
@inner:该标识作为父标识符的内部成员
@instance:标明该标识符作为父标识符的实例成员
@memberof:成员属于哪一个父级标识符
@mixes:此对象混入了另一个对象的所有成员
@mixin:记录一个混入对象
@lends:将一个字面量对象所有属性标记为某个标识符(类或模块)的成员
/** 类型与功能 */
@function:函数
@callback:回调函数
@constant:常量
@member:成员基本种类,如 class、function、constant
@enum:描述一个静态属性值的全部相同的集合,属性的集合
@event:描述一个可触发的事件
@listens:标识监听的事件
@name:强制使用给出的名称忽略代码中的名称
@namespace:指明对象是一个命名空间
/** 作用域 */
@export:描述 exports 或 module.exports 描述的任何内容
@external:描述一个外部类、命名空间或模块
@global:指定一个文档的标识是全局性的标识(全局变量)
配置文件 config.json
和前端很多其他开发工具一样,JSDoc 也有自己的配置文件,叫做config.json
。除了常规的定义 JSDoc 作用的文件范围、标签的配置外,还涉及到在通过jsdoc
命令生成文档时启用的插件和相关配置。
详细的配置项格式说明如下:
{
"tags": {
// 允许使用无法识别的标签
"allowUnknownTags": true,
// 这些标签被启用
"dictionaries": ["jsdoc","closure"]
},
"source": {
// 只有 js 和 jsdoc 结尾的文件将会被处理
"includePattern": ".+\.js(doc)?$",
// 排除文件
"excludePattern": "(^|\/|\\)_"
},
// 插件
"plugins": [],
"templates": {
// @link 标签呈现在纯文本
"cleverLinks": false,
"monospaceLinks": false
}
}
一个在生产环境中的基于 TypeScript 的项目的 config.json 如下,实际开发时可以以此作为模板配置自己的 JSDoc:
{
"plugins": [
"better-docs/component",
"better-docs/category",
"better-docs/typescript",
"plugins/markdown"
],
"typescript": {
"moduleRoot": "src"
},
"recurseDepth": 10,
"opts": {
"destination": "docs",
"recurse": true,
"verbose": true,
"template": "node_modules/better-docs"
},
"source": {
"includePattern": ".+\.ts(doc|x)?$",
"excludePattern": "(^|\/|\\)_"
},
"sourceType": "module",
"tags": {
"allowUnknownTags": true,
"dictionaries": ["jsdoc", "closure"]
},
"templates": {
"cleverLinks": false,
"monospaceLinks": false
}
}
IDE 集成与插件
JSDoc 在 VSCode 和 TypeScript 下均有较好的集成,大部分情况下都是可以作为注释规范开箱即用的,少部分场景下config.json
配置文件也足以覆盖需求。但如果对 JSDoc 的功能有进一步需求的开发者,也可以使用或开发 JSDoc 的插件。
例如 VSCode 拓展中就有不少相关支持,可以根据自己的需求和插件功能自由选择:
而如果需要将项目下散落在不同文件中零散的 JSDoc 统一输出为文档,也可以使用 jsdoc2md、better-docs 等插件。
总结
总体来说,JSDoc 的使用方式是多种多样的,可以仅将其作为与 IDE 有较好集成的前端注释规范参考和注释的 Markdown 格式拓展,也可以作为维护没有 TypeScript 的大型老旧项目的非侵入性类型约束,还能作为高度可配置的自动化文档生成工具。JSDoc 能有效解决项目维护中可能出现的注释风格不统一、注释内容较为随意的问题。此外,JSDoc 中通过概念标签对注释的规范性做出约束、将代码中的注释直接输出为文档的思路也值得我们深思。
参考文章
转载自:https://juejin.cn/post/7392115478561423387