Лучший способ документировать анонимные объекты и функции с помощью jsdoc

Изменить: Это технически вопрос из 2 частей. Я выбрал лучший ответ, который охватывает вопрос в целом и связан с ответом, который обрабатывает конкретный вопрос.

Каков наилучший способ документировать анонимные объекты и функции с помощью jsdoc?

/**
 * @class {Page} Page Class specification
 */
var Page = function() {

    /**
     * Get a page from the server
     * @param {PageRequest} pageRequest Info on the page you want to request
     * @param {function} callback Function executed when page is retrieved
     */
    this.getPage = function(pageRequest, callback) {
    }; 
};

В коде отсутствует объект PageRequest или callback. Они будут предоставлены getPage() во время выполнения. Но я хотел бы иметь возможность определить, что такое объект и функция.

Я могу уйти с созданием объекта PageRequest для документирования того, что:

/**
 * @namespace {PageRequest} Object specification
 * @property {String} pageId ID of the page you want.
 * @property {String} pageName Name of the page you want.
 */
var PageRequest = {
    pageId : null,
    pageName : null
};

И это прекрасно (хотя я открыт для лучших способов сделать это).

Каков наилучший способ документировать функцию callback? Я хочу сообщить в документе, что, например, функция обратного вызова имеет вид:

callback: function({PageResponse} pageResponse, {PageRequestStatus} pageRequestStatus)

Любые идеи, как это сделать?

Ответ 1

Вы можете документировать материал, который не существует в коде, используя тег @name:

        /** Description of the function
            @name IDontReallyExist
            @function
            @param {String} someParameter Description
        */


        /** The CallAgain method calls the provided function twice
            @param {IDontReallyExist} func The function to call twice
        */
        exports.CallAgain = function(func) { func(); func(); }

Вот @документация тегов имен. Вы также можете найти пути имен.

Ответ 2

Вы можете использовать @callback или @typedef.

/**
 * @callback arrayCallback
 * @param  {object} element - Value of array element
 * @param  {number} index   - Index of array element
 * @param  {Array}  array   - Array itself
 */

/**
 * @param {arrayCallback} callback - function applied against elements
 * @return {Array} with elements transformed by callback
 */
Array.prototype.map = function(callback) { ... }

Ответ 3

Чтобы комплимент ответа studgeek, я привел пример, который показывает, что JsDoc с Google Closure Compiler позволяет вам делать.

Обратите внимание, что задокументированные анонимные типы удаляются из сгенерированного мини файла, и компилятор гарантирует, что действительные объекты передаются (когда это возможно). Однако, даже если вы не используете компилятор, он может помочь следующему разработчику и инструментам, таким как WebStorm (IntelliJ), понять это и дать вам завершение кода.

// This defines an named type that you don't need much besides its name in the code
// Look at the definition of Page#getPage which illustrates defining a type inline
/**  @typedef { pageId : string, pageName : string, contents: string} */
var PageResponse;

/**
 * @class {Page} Page Class specification
 */
var Page = function() {    
    /**
     * Get a page from the server
     * @param {PageRequest} pageRequest Info on the page you want to request
     *
     * The type for the second parameter for the function below is defined inline
     *
     * @param {function(PageResponse, {statusCode: number, statusMsg: string})} callback
     *        Function executed when page is retrieved
     */
    this.getPage = function(pageRequest, callback) {
    }; 
};

Ответ 4

@link может добавлять встроенные ссылки на методы и классы.

/**
 * Get a page from the server
 * @param {PageRequest} pageRequest Info on the page you want to request
 * @param {function} callback Function executed when page is retrieved<br />
 * function({@link PageResponse} pageResponse,{@link PageRequestStatus} pageRequestStatus)
 */
this.getPage = function (pageRequest, callback) {
};

Не идеально, но он выполняет свою работу.

Ответ 5

В аннотациях компилятора Google Closure Type Expressions для этого есть возможность указывать тип для конкретных аргументов, тип возвращаемого значения и даже это. Многие библиотеки ищут комментарии к комментариям компилятора Google Closure, потому что они хотят использовать его для сжатия своего кода. Таким образом, он получил некоторый импульс. Недостатком является то, что я не вижу способа дать описание.

Для обеспечения описания, возможно, будет работать подход JSDoc Toolkit Параметры с свойствами (посмотрите в нижней части страницы). Это то, что я делаю прямо сейчас. JSDoc Toolkit готов начать работу над V3, поэтому обратная связь может быть хорошей.

Ответ 6

Вы можете использовать @see для ссылки на другой метод в пределах одного класса. Этот метод никогда не будет использоваться, он просто будет использоваться для целей документации.

/**
 * @class {Page} Page Class specification
 */
var Page = function() {

    /**
     * Get a page from the server
     * @param {PageRequest} pageRequest Info on the page you want to request
     * @param {function} callback Function executed when page is retrieved
     * @see #getPageCallback 
     */
    this.getPage = function (pageRequest, callback) {
    }; 

    /**
     * Called when page request completes 
     * @param {PageResponse} pageResponse The requested page
     * @param {PageRequestStatus} pageRequestStatus Status of the page
     */
    //#ifdef 0
    this.getPageCallback = function (pageResponse, pageRequestStatus) { };
    //#endif 
};

Если вы используете какую-то систему сборки, метод dummy можно легко исключить из сборки.