【JavaScript】文档注释详解

news2024/12/31 6:23:18

文章目录

  • 什么是文档注释
  • 为什么要写文档注释
  • 不使用文档注释存在的隐患
    • 使用函数成员时的书写问题
    • 调用函数时功能使用问题
  • 文档注释
    • 官方标签
      • 函数
      • 参数标签 @param
        • 参数类型 {}
        • 参数注释
        • 对象属性属性注释
          • 使用带有对象属性注释的参数
      • 返回值标签 @returns
        • 注释
      • 作者标签 @author
      • 许可证标签 @license
        • 许可证分类
        • 1. 开源许可证(Open Source Licenses)
        • 2. 版权声明(Copyright Declaration)
        • 3. 私有许可证(Proprietary Licenses)
        • 4. 其他许可证(Other Licenses)
      • 示例标签 @example
      • 定义对象标签 @typedef 和属性标签 @property
      • 异常标签 @throws
      • 废弃标签 @deprecated
    • 约定标签
      • 成员的可见性 @private @protected @public
      • 类 @class 的继承 @extends 与方法的重写 @inheritdoc
      • 类型 @type 与只读 @readonly
      • 类 @class 与构造函数 @constructor
    • 自定义标签
      • 历史记录@history
      • 日期@history
  • 生成文档
    • demo1.js
    • demo2.js
    • demo3.js
    • 1. 安装js文档生成工具
    • 2. 使用js文档生成工具生成文档
    • 3. 查看生成的效果
      • 首页
      • debounce 函数
      • getRandom 函数
      • request 函数


什么是文档注释

在JavaScript中,文档注释是一种特殊的注释格式,用于描述代码的功能、使用方法、参数、返回值等信息。文档注释通常使用特定的注释标记和结构来表示,并且可以通过工具解析生成文档。

在JavaScript中,常用的文档注释格式是使用 /** 和 */ 括起来的多行注释。例如:

/**
 * 这是一个示例函数,用于加法运算。
 * @param {number} a - 第一个操作数
 * @param {number} b - 第二个操作数
 * @returns {number} - 两个操作数的和
 */
function add(a, b) {
  return a + b;
}

上面的代码段中,以 /** 开始和以 */ 结束的多行注释就是文档注释。在注释的内容中,使用了一些特殊的标记来表示相关信息,比如 @param 表示参数,@returns 表示返回值。可以在这些标记后面添加具体的描述和类型信息。


为什么要写文档注释

编写JavaScript的文档注释有助于提高代码的可读性生成易于阅读的API文档明确接口规范辅助调试和维护工作以及促进团队合作和知识共享。这是为了更好地组织和记录代码,并使其更易于理解和使用的最佳实践之一。

  • 提供代码的可读性:文档注释可以帮助其他开发人员更好地理解你的代码。通过提供清晰的注释,可以解释代码的目的、使用方法和重要细节,使代码更易于阅读和维护。

  • 自动生成文档:许多开发工具和框架可以根据代码中的文档注释来自动生成文档。例如,JSDoc 是一个常用的JavaScript文档生成工具,它可以解析文档注释并生成API文档。这样其他开发人员就可以轻松地查看代码的接口和用法。

  • 提供接口定义和规范:通过文档注释,可以明确说明函数、类、方法和参数的用途、类型和预期行为。这不仅帮助其他开发人员正确使用你的代码,还可以在团队协作中提供一致性和规范。

  • 辅助代码调试和维护:当你在调试和维护代码时,文档注释可以提供有关代码功能和实现细节的重要信息。这对于理解复杂的功能和排查问题非常有帮助,尤其是当你需要处理他人编写的代码或长时间未接触的代码时。

  • 促进团队合作和知识共享:文档注释可以为开发团队提供一个共享的知识库,使所有人都能理解代码的功能和实现细节。这有助于提高团队成员之间的沟通和协作,并促进代码质量和一致性。

//行注释对于编辑器来说是无效的注释,虽然func从名字上看上去应该是一个方法,但是编辑器(vscode)不知道它是一个函数

// 函数防抖
function debounce(func,duration = 1000) {
  
}

当鼠标放到函数上时,编辑器并不知道这个函数的功能是“函数防抖”
在这里插入图片描述
当鼠标放到参数func上时,编辑器并不知道这个参数是函数
在这里插入图片描述

不使用文档注释存在的隐患

使用函数成员时的书写问题

在使用函数成员时,能有效的降低书写错误。因此,你在使用函数里面的一些成员的时候

// 函数防抖
function debounce(func,duration = 1000) {
  func.aply
}

如:当你在debounce函数内部使用func.apply,它没有智能提示,因为它不知道apply是一个函数
那你稍微不注意把单词写错成aply,就增加了出错的几率啊。
在开发过程中,有相当一部分程序问题就是由于单词拼写错误导致的。
在这里插入图片描述

有人又说了有AI智能提示不是比文档注释更好用吗?
虽然TypeScript(AI自动补全)就是来解决这个单词书写错误的问题的,毕竟很多项目里面没有上TypeScript (AI自动补全)。这工具也不是你想用就能用的,他涉及到隐私、费用、不支持等等原因。所以TypeScript只能起到锦上添花的作用。

调用函数时功能使用问题

// 函数防抖
function debounce(func,duration = 1000) {
}

debounce

debounce函数使用的时候我们能从这个单词的含义知道,它是一个防抖函数,如果我们把这个函数的名称改成wefwfas,我们不知道他的作用是什么,使用的时候没有任何提示,只知道要传2个参数,至于参数的含义、类型等等都不知道。因此我们最好是写文档注释。

// 函数防抖
function wefwfas(func,duration = 1000) {
}

wefwfas

在这里插入图片描述

/**
 * 
 * @param {*} func 
 * @param {*} duration 
 */
function wefwfas(func,duration = 1000) {
  
}

在这里插入图片描述


文档注释

官方标签

函数

如下我们可以给函数写一个注释函数防抖:

/**
 * 函数防抖
 * @param {*} func 
 * @param {*} duration 
 */
function debounce(func,duration = 1000) {

}

debounce()
  • 当鼠标放到函数上时,它就会提示这个函数的名字是函数防抖
    在这里插入图片描述
  • 当我们使用的时候,同样的可以看到它是函数防抖的函数
    在这里插入图片描述

由于平时封装的函数日积月累,如果不添加文档注释的话,很多函数都忘记其作用了。

参数标签 @param

参数类型 {}

针对函数每一个参数也可以添加文档注释,其中以关键字param(parameter) 开始,格式如下:

  * @param {<type>} <param-name> <comments>
  • param: 参数关键字
  • <type>: 参数类型,
    • * - 支持接收所有类型
    • Number - 只接收一种
    • Function|Number - 兼容多种
  • <param-name>: 名称
  • <comments>: 参数说明

如下所示:

  • 参数func 类型是Function
  • 参数duration类型是Number
/**
 * 函数防抖
 * @param {Function} func 
 * @param {Number} duration 
 */
function debounce(func,duration = 1000) {

}

debounce()

当我们把鼠标放到这个参数上时,编辑器就知道
func是函数。
在这里插入图片描述

/**
 * 函数防抖
 * @param {Function} func 
 * @param {Number} duration 
 */
function debounce(func,duration = 1000) {
  func.call
}

debounce()

所以在实现这个函数的时候,当我们使用func.applyfunc.call这些函数方法的时候都有提示了。
在这里插入图片描述

当我们需要调用这个函数时,鼠标放到调用的函数上的时候,编辑器就会告诉我这个参数是一个函数。
在这里插入图片描述

参数注释

可以给这个参数呢加上注释,如下示例

/**
 * 函数防抖
 * @param {Function} func 防抖的目标函数
 * @param {Number} duration 函数执行前等待的时间
 */
function debounce(func,duration = 1000) {

}

debounce()

现在我们再用鼠标放到参数上看看编辑器会怎么提示我们:
在这里插入图片描述

对象属性属性注释

如果参数是object我们还可以对object的每个属性单独添加注释
``

/**
 * 网络请求
 * @param {object} options 配置对象
 * @param {string} options.url 请求地址
 * @param {'GET'|'POST'} options.method 请求方法
 * @param {object} options.body  
 * @param {object} options.headers  
 */
async function request(options) { }

  • url - 是字符串
  • method - 是字符串选项,可以是GET也可以是POST
  • body - 是对象
  • headers - 是对象
使用带有对象属性注释的参数
/**
 * 网络请求
 * @param {object} options 配置对象
 * @param {string} options.url 请求地址
 * @param {'GET'|'POST'} options.method 请求方法
 * @param {object} options.body  
 * @param {object} options.headers  
 */
async function request(options) { }

request()

我们看看编辑器会怎么提示我们:
在这里插入图片描述

返回值标签 @returns

针对有返回值函数可以添加返回值的注释,其中以关键字returns开始,格式如下:

  * @returns {<type>} <comments>
  • returns: 返回值关键字
  • <type>: 参数类型,
    • * - 支持接收所有类型
    • Number - 只接收一种
    • Function|Number - 兼容多种
  • <comments>: 参数说明

注释

/**
 * 函数防抖
 * @param {Function} func 防抖的目标函数
 * @param {Number} duration 函数执行前等待的时间
 * @returns {Function} 返回一个防抖的函数
 */
function debounce(func,duration = 1000) {

}

debounce()

这样返回值的类型也确定下来了,我们看看编辑器是怎么提示我们的:
在这里插入图片描述

作者标签 @author

可以添加作者有关的注释,其中以关键字author开始,格式如下:

  * @author <author-name> <contact-way>
  • author: 作者信息关键字
  • <author-name>: 作者姓名
  • <contact-way>: 联系方式,可以是个人网页、邮箱等等。例如:<370763160@qq.com>
/**
 * 函数防抖
 * @author ISail <370763160@qq.com>
 * @param {Function} func 防抖的目标函数
 * @param {Number} duration 函数执行前等待的时间
 * @returns {Function} 返回一个防抖的函数
 */
function debounce(func,duration = 1000) {

}

debounce()

我们看看编辑器会怎么提示我们,点击<370763160@qq.com>还可以发邮件。
请添加图片描述

许可证标签 @license

可以添加版权有关的注释,其中以关键字license开始,格式如下:

  * @license <license-info>
  • license: 版权信息关键字
  • <license-info>: 指定代码的许可证信息。可以显示多行

在使用 @license 标签时,开发者应该根据代码的实际许可情况填写适当的许可证信息。这有助于提供清晰的许可证声明,保护代码的知识产权,并促进合规和合理的代码使用。

许可证分类

1. 开源许可证(Open Source Licenses)

这些许可证基于开源原则,允许使用、修改和分发源代码或衍生作品。常见的开源许可证包括MIT许可证、BSD许可证、Apache许可证等。

下面是各种常见许可证之间的差异的详细比较表格:

许可证类型商业使用分发修改源代码发布声明更改分发条件专利许可网络服务使用许可证嵌入
GPL强保护Copyleft
LGPL弱保护可选空白条件
AGPL强保护空白条件
New BSD自由空白条件
Simple BSD自由空白条件
MIT自由空白条件
Apache自由空白条件
Apache 2.0自由空白条件
MPL弱保护空白条件
Mozilla MPL 2弱保护空白条件
CDDL弱保护空白条件
CPL弱保护空白条件
EPL弱保护空白条件
CC弱保护空白条件
CC0自由空白条件
WTFPL自由空白条件

下面是各列的解释:

  • 类型:许可证类型,分类为 “强保护”(对派生作品有限制)和 “弱保护”(提供更大的自由度)。
  • 商业使用:许可证是否允许商业使用。
  • 分发修改:许可证是否允许分发修改后的代码。
  • 源代码发布:许可证是否要求源代码的公开发布。
  • 声明更改:许可证是否要求在修改后的代码中声明更改。
  • 分发条件:许可证对分发软件的条件要求。
  • 专利许可:许可证是否授予使用专利的权利。
  • 网络服务使用:许可证是否允许使用者基于该软件提供网络服务。
  • 许可证嵌入:许可证是否要求在使用软件的产品中嵌入许可证信息。
    请注意,这个表格只提供了对常见许可证之间的主要差异的概述。具体的许可证条款和条件应该参考每个许可证的官方文档和相关说明。选择适当的许可证需要根据项目需求和法律咨询进行综合考虑。另外,这里列出的是一些常见的开源许可证,而还有其他类型的许可证可供选择。

2. 版权声明(Copyright Declaration)

这种分类主要用于声明代码的版权归属,指明作者或组织对代码的所有权。在这种情况下,@license 标签通常包含版权声明和版权所有者的信息。

/**
 * @license
 * 
 * 项目一 版本1.0.0
 * (c) 2023年 ISail
 * 根据“项目一许可证”发布。
 * 
 * https://www.example.com/licenses/myproject-license
 */

在这个例子中,我们假设一个名为 “项目一” 的项目,作者为 ISail。他在注释中使用 @license 标签来声明版权信息。下面是每个部分的解释:

  • 项目一 版本1.0.0:指定了项目的版本号。
  • (c) 2023年 ISail:声明了版权归属于 ISail,即声明了版权归属于,又指明了版权年份。
  • 根据“项目一”许可证发布。:说明代码是根据 “项目一许可证” 发布的。
  • https://www.example.com/licenses/project1-license:提供了一个链接,指向一个包含详细许可证条款的网页。

3. 私有许可证(Proprietary Licenses)

私有许可证用于保护代码的知识产权,限制未经许可的使用和分发。在这种情况下,@license 标签可能包含具体的许可条款和使用限制,以及联系方式以获取许可。

/**
 * @license
 * 
 * 库一 版本2.0.0
 * (c) 2023年 少莫千华无限公司。 保留所有权利。
 * 
 * 这是一款私有软件。严禁未经授权擅自复制或传播本软件或其任何部分。
 * 
 * 如需咨询许可证相关信息, 请联系:
 * 370763160@qq.com
 */

在这个例子中,我们假设一个名为 “库一” 的库,归属于 少莫千华无限公司。。作者明确声明了版权信息,并添加了与私有许可证相关的说明。下面是每个部分的解释:

  • 库一 版本2.0.0:指定了库的版本号。
  • (c) 2023年 少莫千华无限公司。 保留所有权利。:声明了版权归属于少莫千华无限公司。,并表示保留所有权利。
  • 这是一款私有软件。严禁未经授权擅自复制或传播本软件或其任何部分。:明确说明这是一款私有软件,未经许可严禁复制或分发软件或其任何部分。
  • 如需咨询许可证相关信息, 请联系:370763160@qq.com:提供了一个联系方式,以便进行许可证相关的咨询。

4. 其他许可证(Other Licenses)

这个分类用于指定其他不属于常见类别的特定许可证。

/**
 * @license
 * 
 * 项目一 版本1.0.0
 * (c) 2023年 ISail
 * 根据Apache许可证2.0发布
 * 
 * SPDX-License-Identifier: Apache-2.0
 * 
 * 了解更多信息,请访问:
 * https://www.apache.org/licenses/LICENSE-2.0
 */

在这个例子中,我们假设一个名为 “项目一” 的项目,作者为 ISail。他在注释中使用 @license 标签来声明版权信息,并指定了使用的许可证。下面是每个部分的解释:

  • 项目一 版本1.0.0:指定了项目的版本号。
  • (c) 2023年 ISail:声明了版权归属于 ISail,并指明了版权年份。
  • 根据Apache许可证2.0发布:说明代码是根据 Apache License 2.0 发布的。
  • SPDX-License-Identifier: Apache-2.0使用 SPDX许可证标识符明确指定了所采用的许可证。
  • https://www.apache.org/licenses/LICENSE-2.0:提供了一个链接,指向一个包含详细许可证条款的网页。
/**
 * 函数防抖
 * @author ISail <370763160@qq.com>
 * @license MIT
 * @param {Function} func 防抖的目标函数
 * @param {Number} duration 函数执行前等待的时间
 * @returns {Function} 返回一个防抖的函数
 */
function debounce(func,duration = 1000) {

}

debounce()

在这里插入图片描述

示例标签 @example

可以在注释中添加示例,提示如何使用这个函数,其中以关键字example开始,格式如下:

/**
 * 获取指定范围内的随机整数
 * @param {number} min 随机数的最小值
 * @param {number} max 随机数的最大值
 * @return {number} 随机数 
 * @example
 * getRange(1, 10); // 获取[1,10]之间的随机数
 */
function getRandom(min, max) { }

getRandom

我们看看编辑器会怎么提示我们:
在这里插入图片描述

定义对象标签 @typedef 和属性标签 @property

在下面的例子中,使用@typedef关键字定义了一个名为User的类型别名,并使用@property关键字指定了User对象的各个属性及其类型。接下来,getUserInfo函数使用@param关键字指定了参数userId的类型为number,并使用@returns关键字指定了返回值类型为User`对象。

通过使用@typedef关键字,我们可以在文档注释中清晰地指定变量、属性和函数的类型,提高代码可读性和可维护性。

/**
 * 用户对象
 * @typedef {object} User
 * @property {number} id - 用户ID
 * @property {string} name - 用户名
 * @property {string} email - 用户电子邮箱
 * @property {Date} birthday - 用户生日
 */

/**
 * 获取用户信息
 * @param {number} userId - 用户ID
 * @returns {User} - 返回用户对象
 */
function getUserInfo(userId) {
  // ...
}

const user = getUserInfo(123);
console.log(user.name); // 输出用户的用户名

我们看看编辑器会怎么提示我们:在这里插入图片描述

异常标签 @throws

在下面的例子中,divide函数使用@param关键字指定了两个参数的类型为number,使用@returns关键字指定了返回值类型为number,并使用@throws关键字指定了可能抛出的异常类型为Error。在函数内部,通过判断除数是否为0,如果是则抛出一个错误。

通过使用@throws关键字,我们可以提示其他开发者该函数可能抛出的异常,使其在调用函数时能够更好地处理异常情况。而在调用函数处,可以使用try...catch语句捕获并处理异常,避免程序崩溃。

/**
 * 执行除法运算
 * @param {number} dividend - 被除数
 * @param {number} divisor - 除数
 * @returns {number} - 返回除法结果
 * @throws {Error} 如果除数为0,则抛出错误
 */
function divide(dividend, divisor) {
  if (divisor === 0) {
    throw new Error("除数不能为0");
  }
  return dividend / divisor;
}

try {
  const result = divide(10, 0);
  console.log(result);
} catch (error) {
  console.error(error.message);
}

我们看看编辑器会怎么提示我们:
在这里插入图片描述

废弃标签 @deprecated

在下面的例子中,通过使用@deprecated关键字,我们将原来的add函数标记为已废弃,并在注释中说明了该函数已被废弃,建议使用新的addNumbers函数代替。在代码中,我们首先调用了已废弃的add函数来计算两个数字的和,然后使用新的addNumbers函数来计算多个数字的和。

/**
 * @deprecated 该函数已被废弃,请使用新的 addNumbers 函数代替。
 * 将两个数字相加
 * @param {number} a - 第一个数字
 * @param {number} b - 第二个数字
 * @returns {number} - 返回相加的结果
 */
function add(a, b) {
  return a + b;
}

/**
 * 将多个数字相加
 * @param {...number} numbers - 要相加的数字列表
 * @returns {number} - 返回相加的结果
 */
function addNumbers(...numbers) {
  return numbers.reduce((sum, number) => sum + number, 0);
}

console.log(add(2, 3)); // 输出: 5

console.log(addNumbers(2, 3, 4)); // 输出: 9

我们看看编辑器会怎么提示我们:
在这里插入图片描述

约定标签

成员的可见性 @private @protected @public

  • _xxxx - 私有成员
  • @private - 私有成员
  • @protected - 保护成员
  • @public- 公共成员
    在下面的例子中,我们使用了下划线 _ 来约定将属性标记为私有,以表示该属性应该被视为私有成员。在构造函数中,我们使用注释@private来说明该属性是私有的。而在getName方法中,我们并没有使用注释@private,因为该方法是公共的,可以由外部访问。
/**
 * 创建一个动物类
 * @class
 */
class Animal {
  /**
   * 构造函数
   * @param {string} name - 名称
   * @private
   */
  constructor(name) {
    this.name = name; // 公共属性
    this._age = 0; // 私有属性,约定以 "_" 开头
    this._weight = 0; // 私有属性,约定以 "_" 开头
  }

  /**
   * 公共方法 - 获取名称
   * @returns {string} - 返回名称
   * @public
   */
  getName() {
    return this.name;
  }

  /**
   * 保护方法 - 获取年龄
   * @returns {number} - 返回年龄
   * @protected
   */
  _getAge() {
    return this._age;
  }
}

/**
 * 创建一个狗类,继承自动物类
 * @class
 */
class Dog extends Animal {
  /**
   * 构造函数
   * @param {string} name - 名称
   */
  constructor(name) {
    super(name);
    this.breed = "unknown"; // 公共属性
  }

  /**
   * 公共方法 - 获取品种
   * @returns {string} - 返回品种
   * @public
   */
  getBreed() {
    return this.breed;
  }

  /**
   * 公共方法 - 获取年龄和名称
   * @returns {string} - 返回年龄和名称的字符串
   * @public
   */
  getAgeAndName() {
    const age = this._getAge(); // 子类可以访问父类的保护方法
    return `Age: ${age}, Name: ${this.name}`;
  }
}

const animal = new Animal("Animal");
console.log(animal.name); // 可以直接访问公共属性 "name"
console.log(animal._age); // 仍然可以直接访问约定为私有的属性 "_age"

const dog = new Dog("Dog");
console.log(dog.name); // 可以直接访问公共属性 "name"
console.log(dog.breed); // 可以直接访问公共属性 "breed"
console.log(dog._getAge()); // 子类可以调用父类的保护方法 "_getAge"
console.log(dog._age); // 仍然可以直接访问约定为私有的属性 "_age"
console.log(dog.getAgeAndName()); // "Age: 0, Name: Dog"

在上面的例子中,我们使用了命名约定和注释来模拟 @private@public@protected 关键字。约定是使用 _ 开头将属性标记为私有,不使用任何特殊约定将属性标记为公共的。

  • name 属性在 Animal 类中是公共的,可以通过对象实例直接访问。
  • _age 属性和 _getAge 方法在 Animal 类中被约定为私有的,但是在 Dog 类中仍然可以直接访问。
  • breed 属性和 getBreed 方法在 Dog 类中是公共的,可以通过对象实例直接访问。
  • getAgeAndName 方法在 Dog 类中访问了父类Animal_getAge 方法。

请注意,这些约定只是一种标准做法,实际上并不能真正实现属性或方法的私有性或保护性。开发者仍然可以绕过约定直接访问被标记为私有的属性。然而,通过使用约定和注释,我们可以向其他开发者传达哪些成员应该被视为私有或保护,以遵循封装的原则。

类 @class 的继承 @extends 与方法的重写 @inheritdoc

/**
 * 车辆类
 * @class
 */
class Vehicle {
  /**
   * 构造函数
   * @param {string} brand - 品牌
   */
  constructor(brand) {
    this.brand = brand; // 公共属性
  }

  /**
   * 获取品牌信息
   * @returns {string} - 返回品牌信息
   */
  getBrand() {
    return this.brand;
  }
}

/**
 * 汽车类,继承自车辆类
 * @class
 * @extends Vehicle
 */
class Car extends Vehicle {
  /**
   * 构造函数
   * @param {string} brand - 品牌
   * @param {string} model - 型号
   */
  constructor(brand, model) {
    super(brand);
    this.model = model; // 公共属性
  }

  /**
   * @inheritdoc
   */
  getBrand() {
    return super.getBrand();
  }

  /**
   * 获取车辆信息,包括品牌和型号
   * @returns {string} - 返回车辆信息
   */
  getVehicleInfo() {
    const brand = this.getBrand(); // 调用父类的方法
    return `Brand: ${brand}, Model: ${this.model}`;
  }
}

const car = new Car("Toyota", "Camry");
console.log(car.getVehicleInfo()); // "Brand: Toyota, Model: Camry"

在上面的例子中,我们使用了 @extends 标签来说明 Car 类继承自 Vehicle 类。然后,在 getBrand 方法的文档注释中使用了 @inheritdoc 标签来表示该方法继承并重写了父类的方法。

请注意,这里的 @inheritdoc 标签只是一种约定,并不是 JavaScript 文档注释的官方标签。不同的文档生成工具可能会对此标签有不同的处理方式。因此,在实际开发中,你需要根据你所使用的文档生成工具的要求来使用适当的标签或约定。

类型 @type 与只读 @readonly

/**
 * 用户类
 * @class
 */
class User {
  /**
   * 创建一个用户实例
   * @param {string} name - 名称
   */
  constructor(name) {
    /**
     * 用户名称
     * @type {string}
     */
    this.name = name;

    /**
     * 用户ID,只读属性
     * @type {number}
     * @readonly
     */
    this.id = generateUniqueId();
  }
}

const user = new User("Alice");
console.log(user.name); // "Alice"
console.log(user.id); // 使用只读属性,例如:"123456"

user.name = "Bob"; // 可以修改可写属性
user.id = 789; // 尝试修改只读属性,会导致错误

在上述示例中,@readonly 标签用于描述 User 类中的 id 属性。这告诉开发人员该属性是只读的,不能在实例创建后进行修改。这样,开发人员在使用该类时就会知道如何正确操作属性。

请注意,JSDoc 标签是一种约定,不同的工具可能会在生成文档时以不同的方式处理标签。但是,@readonly 是在 JSDoc 规范中定义的标准标签之一,并且受到广泛支持。因此,它被认为是官方标签。

类 @class 与构造函数 @constructor

/**
 * 表示一个人的类
 * @class
 */
class Person {
  /**
   * 创建一个人的实例
   * @constructor
   * @param {string} name - 名字
   * @param {number} age - 年龄
   */
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

// 创建一个人的实例
const person = new Person("Alice", 25);
console.log(person.name); // "Alice"
console.log(person.age); // 25

在上述示例中,@class 标签用于描述 Person 类,它表示一个人的类。类的构造函数使用 @constructor 标签进行注释,以指示这是一个构造函数。

构造函数的文档注释使用 @param 标签描述参数,name 参数表示名字,age 参数表示年龄。这样,在使用该类时,开发人员可以通过文档了解到构造函数所需的参数和其作用。

通过使用 @class@constructor 标签,可以为 JavaScript 类提供清晰的文档注释,使其他开发人员能够更好地理解和使用该类。

自定义标签

请注意,JSDoc 并不对自定义标签提供原生的支持,所以某些工具可能会忽略或不同程度地支持这些标签。但是,通过约定和规范,您可以为您的代码库添加自定义信息,以便更好地记录代码的演化历史。

历史记录@history

/**
 * 计算两个数字的和
 * @param {number} a - 第一个数字
 * @param {number} b - 第二个数字
 * @returns {number} 两个数字的和
 * @history
 * - 2021-01-01  初始版本
 * - 2022-05-15  修复 bug:处理负数的情况
 */
function addNumbers(a, b) {
  return a + b;
}

在上述示例中,自定义的 @history 标签被用来记录代码的发展历程。每一行记录都包含日期和相应的注释。

使用这种方式,您可以在 JSDoc 注释中记录多个版本、修复或改进的历史信息。这样,其他开发人员在查看文档时可以了解到代码的进展和变化。

日期@history

/**
 * 计算两个数字的和
 * @param {number} a - 第一个数字
 * @param {number} b - 第二个数字
 * @returns {number} 两个数字的和
 * @date 2021-01-01 初始版本
 * @date 2022-05-15 修复 bug:处理负数的情况
 */
function addNumbers(a, b) {
  return a + b;
}

在上述示例中,我们使用自定义的 @date 标签来记录代码的日期信息。每个标签都包含日期和相应的注释。

使用这种方式,您可以在 JSDoc 注释中记录特定代码片段的创建日期、修改日期或其他相关日期。这样,其他开发人员在查看文档时可以获得更多的上下文信息。


生成文档

我们可以把这个文档注释,生成一个可读的接口文档

demo1.js

/**
 * 函数防抖
 * @author ISail <370763160@qq.com>
 * @license MIT
 * @param {Function} func 防抖的目标函数
 * @param {Number} duration 函数执行前等待的时间
 * @returns {Function} 返回一个防抖的函数
 */
function debounce(func,duration = 1000) { }

demo2.js

/**
 * 获取指定范围内的随机整数
 * @param {number} min 随机数的最小值
 * @param {aa} max 随机数的最大值
 * @return {aaa} 随机数 
 * @example
 * getRange(1, 10); // 获取[1,10]之间的随机数
 */
function getRandom(min, max) { }

demo3.js

/**
 * 网络请求
 * @param {object} options 配置对象
 * @param {string} options.url 请求地址
 * @param {'GET'|'POST'} options.method 请求方法
 * @param {object} options.body  
 * @param {object} options.headers  
 */
async function request(options) { }

1. 安装js文档生成工具

全局安装jsdoc Document

npm i -g jsdoc

在这里插入图片描述

2. 使用js文档生成工具生成文档

你就可以使用这个jsdoc这个命令了

jsdoc <path>
  • - 文件路径

点斜杆./表示当前目录的所有文件,下面以生成文档的示例。

jsdoc ./

3. 查看生成的效果

首页

在这里插入图片描述

debounce 函数

在这里插入图片描述

getRandom 函数

在这里插入图片描述

request 函数

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/704741.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring cloud 之 eureka

Eureka概述 Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理&#xff0c;SpringCloud将它集成在其子项目spring-cloud-netflix中 在服务注册与发现中&#xff0c;有一个注册中心。当服务器启动的时候&#xff0c;会把当前自己服务器的信息比如服务地址通讯地址…

ubuntu 显卡驱动/cuda/cudnn

显卡驱动 https://www.bilibili.com/video/BV1Zc41137tU/?spm_id_from333.999.0.0&vd_sourced75fca5b05d8be06d13cfffd2f4f7ab5 使用recommended的驱动&#xff0c;open和无open的区别在于无open更适合发挥NVIDIA显卡的全部功能和性能&#xff0c;特别是GPU加速计算等任…

K8S集群安装与部署(Linux系统)

一、环境说明&#xff1a;CentOS7、三台主机&#xff08;Master&#xff1a;10.0.0.132、Node1&#xff1a;10.0.0.133、Node2&#xff1a;10.0.0.134&#xff09; 二、准备环境&#xff1a; 映射 关闭防火墙 三、etcd集群配置 安装etcd&#xff08;Master&#xff09; [ro…

[源码分析]-xxljob(1): 整体介绍

xxljob是一种分布式的调度框架&#xff0c;所谓分布式调度&#xff0c;是指调度器和执行器不在同一个进程里&#xff0c;因此必须进行远程服务调用&#xff0c;也需要考虑高可用问题。 但是由于调度器维护的数据是落库而在各个节点间共享的&#xff0c;因此不需要考虑数据的一…

必备数据可视化工具大揭秘

探索数据的美妙世界&#xff01;我们为您带来了一份精心策划的数据可视化工具分享合集。在这个数字时代&#xff0c;数据可视化是理解和传达数据的关键&#xff0c;而这些工具将帮助您以令人惊叹的方式展现数据的潜力。 分享一&#xff1a;伙伴云 伙伴云是一个提供仪表盘和可…

vscode超炫酷的编码特效详解

1.在扩展中搜索 插件&#xff1a;Power Mode 2.在设置里搜索Code Actions On Save 3.点击在settings.json中编辑 {"powermode.enabled": true, //启动// "powermode.presets": "flames", // 火花效果 // 炸裂// "powermode.presets&quo…

织梦宏,解锁元音之谜

本篇博客会讲解力扣“2586. 统计范围内的元音字符串数”的解题思路&#xff0c;这是题目链接。 本题可以使用一个宏来判断一个字符是不是元音字母&#xff0c;接着遍历字符串数组&#xff0c;统计满足条件的字符串个数。 需要满足的条件有&#xff1a; 第一个字符是元音字母。…

微信小程序 滚动到底部加载新的数据 之后滚动到顶部

1.配置到底部监听 在app.json的window里面加入 里面的300表示距离底部300rpx触发onReachBottom事件 默认50rpx "window": {"onReachBottomDistance": 300}, 2.在数据列表的js页面 /*** 页面上拉触底事件的处理函数*/onReachBottom() {console.log("…

采用 CD4011 的温度监测自动控制电路

该电路结构简单&#xff0c;制作容易&#xff0c;由一只与非门和一只热敏电阻组成测控电路和警笛声发声电路&#xff0c;由一只继电器作为执行电路。 一、电路工作原理 电路原理如图 8 所示。 测温电阻RT接在控制门D1的输入端&#xff0c;它和电阻R1、R2及RP通过RP的分压调节…

Cesium入门之十一:认识Cesium中的Entity

目录 Entity类简介Entity在Cesium中的作用Entity的常用属性使用Entity创建点、线、面常用的Entity图形对象及其属性创建点、线、面的方法创建点创建线创建面将点、线、面添加到viewer中 修改Entity的外观和样式点&#xff08;Point&#xff09;的外观样式线&#xff08;Polylin…

蓝奥声核心技术——无线协同代理技术

1.技术背景 无线协同代理技术指基于对目标场景状态变化的协同感知而获得触发响应并进行智能决策&#xff0c;属于蓝奥声核心技术--边缘协同感知(EICS&#xff09;技术的关键支撑性技术之一。该项技术涉及物联网边缘域的无线通信技术领域&#xff0c;具体主要涉及网络服务节点与…

mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入

文章目录 背景说明 背景说明 我这里主要针对2处地方要进行增量执行sql&#xff1a; 1.新功能需要创建一张新表结构indicator_alarm_threshold2.给菜单表和另一个表新增数据 我们现在使用的是项目启动先初始化加载init-table.sql的脚本(这里面的轻易不动了&#xff0c;保持原…

浏览器测试的三大挑战及解决方案

目录 跨浏览器测试&#xff0c;为什么重要 跨浏览器测试挑战及其解决方案 自动化挑战大 解决方案&#xff1a;正确选择工具 设施维护负担大 解决方案&#xff1a;选择可靠的云服务 浏览器适配列表太多 解决方案&#xff1a;选择多版本支持的平台 总结&#xff1a; 随着…

关于Nuxt3.6兼容低版本游览器的实战以及可能存在的问题

当我们网站打包上线后&#xff0c;有些问题我们肯定也要考虑在内&#xff0c;兼容性也是其中一个重要的一种&#xff0c;可能会有人说&#xff0c;都2023年了&#xff0c;还在乎那些废弃的游览器干啥&#xff0c;我只能说&#xff0c;错&#xff01;大错特错&#xff01; 我们不…

docker方式安装gitlab

一&#xff1a;docker 方式安装gitlab 用docker来安装比较方便简单&#xff0c;包括版本升级也会变得更简单。 1、拉取gitlab镜像 gitlab-ce表示的是社区免费版本 docker pull gitlab/gitlab-ce:latest2、创建映射文件 mkdir -p /data/docker/gitlab/etc mkdir -p /data/do…

虚拟现实(VR)在医疗保健中的5种应用

医疗保健中的VR虚拟现实 虚拟现实的由来已久&#xff0c;18世纪&#xff0c;法国的医生使用布制的分娩模拟器向助产师和外科医生教授医学技术。在20世纪60年代初&#xff0c;医生一边对心肺复苏学员口述心肺复苏的技巧&#xff0c;一边使用一家塑料玩具厂家制造的塑料娃娃现场…

前端开发工程师的自我修养:前端开发工程师必须掌握的 Promise(详解)以及在 Vue3 项目中的实战应用

文章目录 &#x1f4cb;前言&#x1f3af;关于 promise&#xff08;用于使用 JavaScript 编写的 Windows 应用商店应用&#xff09;的内容分享&#x1f9e9;promise 究竟是什么&#xff1f;承诺关系 &#x1f3af;JavaScript Promise&#x1f9e9;认识了解 Promise &#x1f3a…

RK3568平台开发系列讲解(外设篇)HX711调试

🚀返回专栏总目录 文章目录 一、HX711 工作原理二、硬件连接三、驱动四、修改设备树五、测试沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将讲解 HX711 模块调试。 一、HX711 工作原理 该部分由应变片与 HX711 模数转换器组成。应变片上的压力变化引起应…

线程基础、线程之间的共享和协作(初篇)

什么是进程和线程&#xff1f; 进程是操作系统进行资源分配的最小单位。资源包括cpu&#xff0c;内存空间&#xff0c;磁盘io等。同一进程里的多个线程共享该进程的全部系统资源。而进程与进程之间是相互独立的。 线程是cpu调度的最小单位&#xff0c;必须依托于进程而存在。…

高斯金字塔的秘密,尺度空间证明的思考

在构建图像尺度空间的过程中&#xff0c;唯一使用的核函数是高斯核&#xff0c;这一点被T Lindeber在文献《Scale-space theory: a basic tool for analyzing structures at different scales》中证明&#xff0c;高斯核是唯一可以产生多尺度空间的核。 相信大家在使用高斯金字…