【JSDoc】都2024年了,你不会还在用纯文本写注释吧

使用背景

在很多存量的项目中,可能很多项目都没有上ts,以及开发人员的注释写的云里雾里。比如以下场景,当你接手这种代码时,你会不会跟我一样想params要传什么?这个函数有没有返回值?返回值是什么?

javascript 复制代码
// 获取用户信息
function getUser (params) {
    // code
}

当你跟我有相同的疑问时,我们何妨不花几分钟来了解今天的主角jsdoc,来优化我们的🪨山代码呢~~

主要关键字使用说明

@typedef

语法: [<type>] <namepath>

使用场景:声明一个自定义类型,可以用于函数入参出参,类型于typesript的type定义

javascript 复制代码
/**
 * @typedef {Object} User
 * @property {string} User.name - 用户姓名
 * @property {number} User.age - 用户年龄
 */
 
 
 /**
 * @param {User} 查询的用户
 * @returns {number} 用户年龄
 */
function getUserAge(user) {
  return user.age
}

效果:调用函数就会根据定义的类型来进行智能推断


@enum

语法:@enum <type> 使用场景:定义一个对象为枚举类型,可以直接使用该对象作为入参类型,一般配合@readonly使用,因为枚举值正常来说是不能被更改的。

javascript 复制代码
/**
 * @readonly
 * @enum {'1' | '2'}
 */
const SEX = {
  MALE: '1',
  FEMALE: '2',
}

@callback

语法:@callback <namepath>

使用场景:定义回调函数的类型,以充当其他函数的入参类型。 比单纯使用Function类型来定义入参会更加的清晰知道回调函数需要几个入参,以及出参。

javascript 复制代码
/**
 * 过滤特定年龄用户回调函数
 * @callback RequestUserFilterCallback
 * @param {User[]} users 用户数组
 * @param {number} limitAge 年龄条件
 * @returns {User[]} 符合条件的用户
 */


/**
 * 获取用户
 * @param {RequestUserFilterCallback} cb 过滤函数
 */
async function fetchUser (cb) {
  const users = await fetch('get/users')
  return cb(users, 18)
}

fetchUser((users, limitAge) => users.age <= limitAge)

效果:调用函数的时候就会有对应的回调类型提示


@param

语法:@param [<type>] <name> [<description>]

使用场景:建议每个函数的入参都使用@param来进行标注,不仅可以使开发者清晰地知道每个入参的意义,而且在使用函数的时候编辑器也会有对应的类型提示。

必填参数使用示例

javascript 复制代码
// 这里的类型可以使用javascript的基本类型或者自定义类型

/**
 * @readonly
 * @enum {'1' | '2'}
 */
const SEX = {
  MALE: '1',
  FEMALE: '2',
}

/**
 * 自定义用户类型
 * @typedef {Object} User
 * @property {string} User.name - 用户姓名
 * @property {number} User.age - 用户年龄
 */

/**
 * 给用户增加性别
 * @param {User} user 查询的用户
 * @param {SEX} sex 用户性别
 * @returns {User & {sex: SEX}} 具有性别属性的用户
 */
function addUserSex(user, sex) {
  return {...user, sex}
}

效果:写好函数入参,出参的类型标注,编辑器会获得类型提示,减少开发理解和使用成本。

可选参数使用示例

给参数增加[],代表可选参数

javascript 复制代码
/**
 * 获取用户性别
 * @param {User} [user] 查询的用户,可能为空
 * @returns {SEX | null}
 */
function getUserSex (user) {
  if (user) {
    return user.sex
  }
  return null
}

getUserSex()

效果:


@this

语法:@this 声明的对象

使用场景:声明当前函数的this指向,在非纯函数的编程环境中,this的指向经常是编辑器无法推断的,而且对其他开发人员也不够清晰,使用@this可以清晰地告诉外界当前函数的this指向

javascript 复制代码
/**
 * @description jsdoc this 使用示例
 * @this Vue
 */
function testThis () {
  this.$alert('123')
}

效果:此时调用函数时编辑器会识别并且有智能提醒


@todo

语法:@todo 描述要实现的事情

使用场景:当版本功能还未完成时,用@todo标记后续待实现的功能。

javascript 复制代码
/**
 * 实现一个使用例子
 * @todo 增加例子
 * @todo 增加注释
 */
function createExample () {}

@example

使用场景:给函数增加使用例子,特别是参数较多的函数,建议多种情况的例子都标注好。

javascript 复制代码
/**
 * 两数相加
 * @param {number} num1 相加数字
 * @param {number} num2 相加数字
 * @returns {number} 两数之和
 * @example
 * add(1, 2) // 3
 */
function add (num1, num2) {
  return num1 + num2
}

效果:调用函数的时候可以看到标注的例子如何进行使用


@deprecated

语法:@deprecated [废弃的原因及指引] 使用场景:当版本升级后,原有代码需要逐步替换时,标注好什么代码在日后不使用以及指引如何切换到新代码,对于版本升级/重构代码时可让团队开发人员清晰知道被标注的代码已废弃。

javascript 复制代码
/**
 * @deprecated 从版本1.0后废弃,登录功能请使用loginV2函数
 */
function login () {}

效果:调用被标注的内容时,编辑器会自动识别到该方法已废弃,并且展示废弃的指引内容。


总结

使用jsdoc有以下的优势

  1. 提高代码的可读性,提高项目代码可维护性
  2. 可以在不引入typescript的同时,使用typescript的类型标注,代码静态提示等功能,这在一些老项目的时候非常实用
  3. 对项目代码无副作用,例如运行构建变慢,代码改造等都无需担心
  4. 配合现代编辑器可以有很好的智能提醒,减少因手写错误等低级错误的产生

注意事项

  1. jsdoc并不能代替typescript的功能,它只是一个规范的约束,并不能保证类型安全。
  2. 建议公用代码及公用组件一定要进行良好的类型标注及例子说明。

上述例子只是列举来一些比较常用的场景,还有更多深入的玩法可以参考jsdoc官方网站

相关推荐
码事漫谈1 小时前
大模型输出的“隐性结构塌缩”问题及对策
前端·后端
这儿有一堆花1 小时前
前端三件套真的落后了吗?揭开现代 Web 开发的底层逻辑
前端·javascript·css·html5
.Cnn2 小时前
JavaScript 前端基础笔记(网页交互核心)
前端·javascript·笔记·交互
醉酒的李白、2 小时前
Vue3 组件通信本质:Props 下发,Emits 回传
前端·javascript·vue.js
anOnion2 小时前
构建无障碍组件之Window Splitter Pattern
前端·html·交互设计
NotFound4863 小时前
实战分享Python爬虫,如何实现高效解析 Web of Science 文献数据并导出 CSV
前端·爬虫·python
徐小夕3 小时前
PDF无限制预览!Jit-Viewer V1.5.0开源文档预览神器正式发布
前端·vue.js·github
WangJunXiang63 小时前
Haproxy搭建Web群集
前端
吴声子夜歌3 小时前
Vue.js——自定义指令
前端·vue.js·flutter
小芝麻咿呀4 小时前
vue--面试题第一部分
前端·javascript·vue.js