本文介绍: 在JavaScript中,文档注释是一种特殊注释格式用于描述代码功能使用方法参数返回值信息文档注释通常使用特定的注释标记结构来表示,并且可以通过工具解析生成文档。在JavaScript中,常用的文档注释格式使用 /** 和 */ 括起来的多行注释。/*** 这是一个示例函数,用于加法运算。* @param {number} a – 第一个操作数* @param {number} b第二个操作数* @returns {number} – 两个操作数的和。


什么是文档注释

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

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

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

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


为什么要写文档注释

编写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&gt;} <param-name&gt; <comments&gt;

如下所示:

  • 参数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) { }

使用带有对象属性注释的参数
/**
 * 网络请求
 * @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&gt;} <comments&gt;
注释
/**
 * 函数防抖
 * @param {Function} func 防抖的目标函数
 * @param {Number} duration 函数执行等待时间
 * @returns {Function} 返回一个防抖的函数
 */
function debounce(func,duration = 1000) {

}

debounce()

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

作者标签 @author

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

  * @author <author-name> <contact-way>
/**
 * 函数防抖
 * @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 标签声明版权信息。下面是每个部分的解释

3. 私有许可证(Proprietary Licenses)

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

/**
 * @license
 * 
 * 库一 版本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

/**
 * 创建一个动物类
 * @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 函数

在这里插入图片描述

原文地址:https://blog.csdn.net/chenlu5201314/article/details/131482196

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_16645.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注