JSDoc能否记录动态生成的方法?

7

这里有一个构造函数 A,它会创建实例并提供两个方法:printThingprintBall。我使用 JSDoc 来记录这些方法:

var A = function () {

    /**
     * Prints 'Thing'
     * @param {Number} N - The number of times to print.
     */
    this.printThing = function (N) {
        var i = 0;
        while (i < N) {
            console.log('Thing');
            i++
        }
    };

    /**
     * Prints 'Ball'
     * @param {Number} N - The number of times to print.
     */
    this.printBall = function (N) {
        var i = 0;
        while (i < N) {
            console.log('Ball');
            i++
        }
    };

};

这里有一个等效的构造函数,可以动态生成与此相同的方法:
var A = function () {

    var me = this;
    var registerPrinter = function (name) {
        me['print' + name] = function (N) {
            var i = 0;
            while (i < N) {
                console.log(name);
                i++;
            }
        };
    };

    registerPrinter('Thing');
    registerPrinter('Ball');
}

两个构造函数生成的实例的行为是相同的:
> var a = new A();
> a.printBall(4);
Ball
Ball
Ball
Ball

我该如何使用JSDoc来记录第二个A构造函数中生成的方法?
编辑:registerPrinter在构造函数的范围内是私有的。它可以(并且应该)被记录,但它只是在内部使用。这个问题是关于记录A实例的公共接口的。

我发现这个文档很有用:http://usejsdoc.org/about-namepaths.html - Alex Ilyaev
3个回答

7

@name标签是用来实现这个功能的:

该标签最好用于“虚拟注释”,用于那些在代码中不容易看到的符号...

ES6:

/** Class A */
class A {
    constructor () {
        ['Thing', 'Ball'].map((name) => {
            this['print' + name] = (N) => {
                let i = 0;
                while (i < N) {
                    console.log(name);
                    i++;
                }
            };
        });
    }
}

/**
 * @name A#printThing
 * @function
 * @memberof A
 * @description Prints 'Thing'
 * @param {Number} N - The number of times to print.
 */

/**
 * @name A#printBall
 * @function
 * @memberof A
 * @description Prints 'Ball'
 * @param {Number} N - The number of times to print.
 */

ES5:

/**
 * @class A
 */
var A = function () {

    var me = this;
    var registerPrinter = function (name) {
        me['print' + name] = function (N) {
            var i = 0;
            while (i < N) {
                console.log(name);
                i++;
            }
        };
    };

    ['Thing', 'Ball'].map(registerPrinter);

    /**
     * @name A#printThing
     * @function
     * @memberof A
     * @description Prints 'Thing'
     * @param {Number} N - The number of times to print.
     */

    /**
     * @name A#printBall
     * @function
     * @memberof A
     * @description Prints 'Ball'
     * @param {Number} N - The number of times to print.
     */
}

这是一个很好的解决方案,比我的回答更直接地回答了我的问题。谢谢你抽出时间来回答! - kdbanman
好的解决方案。但我在想,如何更轻松地处理大量动态生成的方法。写所有这些方法可能会很繁琐。 - keshav.bahadoor
最终我使用了一个脚本,根据我的一些逻辑将文档输出到另一个.js文件中。然后我对主目标文件和生成的文件都使用了jsdoc命令。对于我超过30个动态生成的方法的情况来说,效果还不错。 - keshav.bahadoor
@keshav.bahadoor 如果没有看到你的代码,很难说,但如果你可以动态生成方法和文档(它们做的是同样的事情?),也许你应该考虑根本不生成30个方法。 - Peter

1
在一天的文档搜索后,这是我能找到的最佳选项。它需要稍微不同的A等效定义,并更改registerPrinter。它略微冗长,但保留了不重复非常相似方法的可维护性优势,并且更易读:
var A = function () {

    var generatePrinter = function (name) {
        return function (N) {
            var i = 0;
            while (i < N) {
                console.log(name);
                i++;
            }
        };
    };

    /**
     * Prints 'Thing'
     * @param {Number} N - The number of times to print.
     */
    this.printThing = generatePrinter('Thing');

    /**
     * Prints 'Ball'
     * @param {Number} N - The number of times to print.
     */
    this.printBall = generatePrinter('Ball');
}

请注意,现在不再动态地将属性printThingprintBall添加到this中(虽然方法仍然是动态生成的)。因此,这不是直接解决问题的方法 - 它是一种解决方法。如果有任何未来的答案实际上记录了动态添加的属性,我将接受它。

0
为什么不直接记录已编写的代码呢?
var A = function() {

  var me = this;

  /**
   * [function description]
   * @param  {[type]} name [description]
   * @return {[type]}      [description]
   */
  var registerPrinter = function(name) {

    /**
     * [function description]
     * @param  {[type]} N [description]
     * @return {[type]}   [description]
     */
    me['print' + name] = function(N) {
      var i = 0;
      while (i < N) {
        console.log(name);
        i++;
      }
    };
  };

  registerPrinter('Thing');
  registerPrinter('Ball');
};

感谢您的回复。registerPrinter 在构造函数范围内是私有的。它可以(而且应该)被记录,但它只是在内部使用。我想记录 A 实例的公共接口。抱歉这不够清晰 - 我会在我的问题中注明这一点。 - kdbanman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接