2.4 注释

2.4.1 单行注释

【强制】 必须独占一行。// 后跟一个空格,缩进与下一行被注释说明的代码一致。

2.4.2 多行注释

【建议】 避免使用 /*...*/ 这样的多行注释。有多行注释内容时,使用多个单行注释。

2.4.3 文档化注释

【强制】 为了便于代码阅读和自文档化,以下内容必须包含以 /**...*/ 形式的块注释中。

解释:

  1. 文件
  2. namespace
  3. 函数或方法
  4. 类属性
  5. 事件
  6. 全局变量
  7. 常量
【强制】 文档注释前必须空一行。
【建议】 自文档化的文档说明 what,而不是 how。

2.4.4 类型定义

【强制】 类型定义都是以{开始, 以}结束。

解释:

常用类型如:{string}, {number}, {boolean}, {Object}, {Function}, {RegExp}, {Array}, {Date}。

类型不仅局限于内置的类型,也可以是自定义的类型。比如定义了一个类 Developer,就可以使用它来定义一个参数和返回值的类型。

【强制】 对于基本类型 {string}, {number}, {boolean},首字母必须小写。
类型定义 语法示例 解释
String {string}
Number {number}
Boolean {boolean}
Object {Object}
Function {Function}
RegExp {RegExp}
Array {Array}
Date {Date}
单一类型集合 {Array.<string>} string 类型的数组
多类型 {(number|boolean)} 可能是 number 类型, 也可能是 boolean 类型
允许为null {?number} 可能是 number, 也可能是 null
不允许为null {!Object} Object 类型, 但不是 null
Function类型 {function(number, boolean)} 函数, 形参类型
Function带返回值 {function(number, boolean):string} 函数, 形参, 返回值类型
参数可选 @param {string=} name 可选参数, =为类型后缀
可变参数 @param {…number} args 变长参数, …为类型前缀
任意类型 {*} 任意类型
可选任意类型 @param {*=} name 可选参数,类型不限
可变任意类型 @param {…*} args 变长参数,类型不限

2.4.5 文件注释

【强制】 文件顶部必须包含文件注释,用 @file 标识文件说明。

示例:

  1. /**
  2. * @file Describe the file
  3. */
【建议】 文件注释中可以用 @author 标识开发者信息。

解释:

开发者信息能够体现开发人员对文件的贡献,并且能够让遇到问题或希望了解相关信息的人找到维护人。通常情况文件在被创建时标识的是创建者。随着项目的进展,越来越多的人加入,参与这个文件的开发,新的作者应该被加入 @author 标识。

@author 标识具有多人时,原则是按照 责任 进行排序。通常的说就是如果有问题,就是找第一个人应该比找第二个人有效。比如文件的创建者由于各种原因,模块移交给了其他人或其他团队,后来因为新增需求,其他人在新增代码时,添加 @author 标识应该把自己的名字添加在创建人的前面。

@author 中的名字不允许被删除。任何劳动成果都应该被尊重。

业务项目中,一个文件可能被多人频繁修改,并且每个人的维护时间都可能不会很长,不建议为文件增加 @author 标识。通过版本控制系统追踪变更,按业务逻辑单元确定模块的维护责任人,通过文档与wiki跟踪和查询,是更好的责任管理方式。

对于业务逻辑无关的技术型基础项目,特别是开源的公共项目,应使用 @author 标识。

示例:

  1. /**
  2. * @file Describe the file
  3. * @author author-name(mail-name@domain.com)
  4. * author-name2(mail-name2@domain.com)
  5. */

2.4.6 命名空间注释

【建议】 命名空间使用 @namespace 标识。

示例:

  1. /**
  2. * @namespace
  3. */
  4. var util = {};

2.4.7 类注释

【建议】 使用 @class 标记类或构造函数。

解释:

对于使用对象 constructor 属性来定义的构造函数,可以使用 @constructor 来标记。

示例:

  1. /**
  2. * 描述
  3. *
  4. * @class
  5. */
  6. function Developer() {
  7. // constructor body
  8. }
【建议】 使用 @extends 标记类的继承信息。

示例:

  1. /**
  2. * 描述
  3. *
  4. * @class
  5. * @extends Developer
  6. */
  7. function Fronteer() {
  8. Developer.call(this);
  9. // constructor body
  10. }
  11. util.inherits(Fronteer, Developer);
【强制】 使用包装方式扩展类成员时, 必须通过 @lends 进行重新指向。

解释:

没有 @lends 标记将无法为该类生成包含扩展类成员的文档。

示例:

  1. /**
  2. * 类描述
  3. *
  4. * @class
  5. * @extends Developer
  6. */
  7. function Fronteer() {
  8. Developer.call(this);
  9. // constructor body
  10. }
  11. util.extend(
  12. Fronteer.prototype,
  13. /** @lends Fronteer.prototype */{
  14. _getLevel: function () {
  15. // TODO
  16. }
  17. }
  18. );
【强制】 类的属性或方法等成员信息使用 @public / @protected / @private 中的任意一个,指明可访问性。

解释:

生成的文档中将有可访问性的标记,避免用户直接使用非 public 的属性或方法。

示例:

  1. /**
  2. * 类描述
  3. *
  4. * @class
  5. * @extends Developer
  6. */
  7. var Fronteer = function () {
  8. Developer.call(this);
  9. /**
  10. * 属性描述
  11. *
  12. * @type {string}
  13. * @private
  14. */
  15. this._level = 'T12';
  16. // constructor body
  17. };
  18. util.inherits(Fronteer, Developer);
  19. /**
  20. * 方法描述
  21. *
  22. * @private
  23. * @return {string} 返回值描述
  24. */
  25. Fronteer.prototype._getLevel = function () {
  26. };

2.4.8 函数/方法注释

【强制】 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。
【强制】 参数和返回值注释必须包含类型信息和说明。
【建议】 当函数是内部函数,外部不可访问时,可以使用 @inner 标识。

示例:

  1. /**
  2. * 函数描述
  3. *
  4. * @param {string} p1 参数1的说明
  5. * @param {string} p2 参数2的说明,比较长
  6. * 那就换行了.
  7. * @param {number=} p3 参数3的说明(可选)
  8. * @return {Object} 返回值描述
  9. */
  10. function foo(p1, p2, p3) {
  11. var p3 = p3 || 10;
  12. return {
  13. p1: p1,
  14. p2: p2,
  15. p3: p3
  16. };
  17. }
【强制】 对 Object 中各项的描述, 必须使用 @param 标识。

示例:

  1. /**
  2. * 函数描述
  3. *
  4. * @param {Object} option 参数描述
  5. * @param {string} option.url option项描述
  6. * @param {string=} option.method option项描述,可选参数
  7. */
  8. function foo(option) {
  9. // TODO
  10. }
【建议】 重写父类方法时, 应当添加 @override 标识。如果重写的形参个数、类型、顺序和返回值类型均未发生变化,可省略 @param@return,仅用 @override 标识,否则仍应作完整注释。

解释:

简而言之,当子类重写的方法能直接套用父类的方法注释时可省略对参数与返回值的注释。

2.4.9 事件注释

【强制】 必须使用 @event 标识事件,事件参数的标识与方法描述的参数标识相同。

示例:

  1. /**
  2. * 值变更时触发
  3. *
  4. * @event
  5. * @param {Object} e e描述
  6. * @param {string} e.before before描述
  7. * @param {string} e.after after描述
  8. */
  9. onchange: function (e) {
  10. }
【强制】 在会广播事件的函数前使用 @fires 标识广播的事件,在广播事件代码前使用 @event 标识事件。
【建议】 对于事件对象的注释,使用 @param 标识,生成文档时可读性更好。

示例:

  1. /**
  2. * 点击处理
  3. *
  4. * @fires Select# change
  5. * @private
  6. */
  7. Select.prototype.clickHandler = function () {
  8. /**
  9. * 值变更时触发
  10. *
  11. * @event Select# change
  12. * @param {Object} e e描述
  13. * @param {string} e.before before描述
  14. * @param {string} e.after after描述
  15. */
  16. this.fire(
  17. 'change',
  18. {
  19. before: 'foo',
  20. after: 'bar'
  21. }
  22. );
  23. };

2.4.10 常量注释

【强制】 常量必须使用 @const 标记,并包含说明和类型信息。

示例:

  1. /**
  2. * 常量说明
  3. *
  4. * @const
  5. * @type {string}
  6. */
  7. var REQUEST_URL = 'myurl.do';

2.4.11 复杂类型注释

【建议】 对于类型未定义的复杂结构的注释,可以使用 @typedef 标识来定义。

示例:

  1. // `namespaceA~` 可以换成其它 namepaths 前缀,目的是为了生成文档中能显示 `@typedef` 定义的类型和链接。
  2. /**
  3. * 服务器
  4. *
  5. * @typedef {Object} namespaceA~Server
  6. * @property {string} host 主机
  7. * @property {number} port 端口
  8. */
  9. /**
  10. * 服务器列表
  11. *
  12. * @type {Array.<namespaceA~Server>}
  13. */
  14. var servers = [
  15. {
  16. host: '1.2.3.4',
  17. port: 8080
  18. },
  19. {
  20. host: '1.2.3.5',
  21. port: 8081
  22. }
  23. ];

2.4.12 细节注释

对于内部实现、不容易理解的逻辑说明、摘要信息等,我们可能需要编写细节注释。

【建议】 细节注释遵循单行注释的格式。说明必须换行时,每行是一个单行注释的起始。

示例:

  1. function foo(p1, p2) {
  2. // 这里对具体内部逻辑进行说明
  3. // 说明太长需要换行
  4. for (...) {
  5. ....
  6. }
  7. }
【强制】 有时我们会使用一些特殊标记进行说明。特殊标记必须使用单行注释的形式。下面列举了一些常用标记:

解释:

  1. TODO: 有功能待实现。此时需要对将要实现的功能进行简单说明。
  2. FIXME: 该处代码运行没问题,但可能由于时间赶或者其他原因,需要修正。此时需要对如何修正进行简单说明。
  3. HACK: 为修正某些问题而写的不太好或者使用了某些诡异手段的代码。此时需要对思路或诡异手段进行描述。
  4. XXX: 该处存在陷阱。此时需要对陷阱进行描述。