第 29 章。JSDoc:產生 API 文件
目錄
購買書籍
(廣告,請勿封鎖。)

第 29 章。JSDoc:產生 API 文件

這是 常見的開發問題:您編寫了 JavaScript 程式碼供他人使用,並需要其 API 的美觀 HTML 文件。在 JavaScript 世界中,用於產生 API 文件的實際標準工具是 JSDoc[23] 它仿照其 Java 類比 JavaDoc 建模。

JSDoc 使用帶有 /** */ 註解的 JavaScript 程式碼(以星號開頭的正常區塊註解),並為其產生 HTML 文件。例如,給定以下程式碼:

/** @namespace */
var util = {
    /**
     * Repeat <tt>str</tt> several times.
     * @param {string} str The string to repeat.
     * @param {number} [times=1] How many times to repeat the string.
     * @returns {string}
     */
    repeat: function(str, times) {
        if (times === undefined || times < 1) {
            times = 1;
        }
        return new Array(times+1).join(str);
    }
};

產生的 HTML 在網頁瀏覽器中看起來如 圖 29-1 所示。

JSDoc 網站上的 自述檔 說明如何安裝和呼叫此工具。

JSDoc 的基礎

JSDoc 旨在記錄 實體(函式、方法、建構函式等)。這是透過在實體之前加上以 /** 開頭的註解來達成。

語法

讓我們檢閱 一開始顯示的註解:

/**
 * Repeat <tt>str</tt> several times.
 * @param {string} str The string to repeat.
 * @param {number} [times=1] How many times to repeat the string.
 * @returns {string}
 */

這展示了部分 JSDoc 語法,它包含以下部分

JSDoc 註解
這是第一個字元為星號的 JavaScript 區塊註解。這會產生令牌 /** 開頭此類註解的錯覺。
標籤
您可以透過以 標籤 開頭行來建構 註解,這些標籤是加上 @ 符號為字首的關鍵字。 @param 是前述程式碼中的範例。
HTML
您可以在 JSDoc 註解中 自由使用 HTML。例如, <tt> 會以等寬字型顯示一個字詞。
類型註解

您可以透過大括弧中的類型名稱來記錄實體的類型。變異包括:

  • 單一類型: @param {string} name
  • 多個類型: @param {string|number} idCode
  • 類型陣列:@param {string[]} names
名稱路徑

在 JSDoc 註解中,所謂的 名稱路徑 用於參照實體。此類路徑的語法如下

myFunction
MyClass
MyClass.staticMember
MyClass#instanceMember

類別 通常由建構函式(實作)。例如,靜態成員是建構函式的屬性。JSDoc 對 實例成員 有廣泛的定義。其意指可透過實例存取的一切內容。因此,實例成員包括實例屬性和原型屬性。

命名類型

實體的類型 為基本類型或類別。前者的名稱總是從小寫字母開始;後者的名稱總是從大寫字母開始。換句話說,基本類型的名稱為 booleannumberstring,就像 typeof 營運子傳回的結果一樣。這樣一來,您就不會將字串(基本類型)與建構函式 String(物件)的實例混淆。

基本標籤

以下是基本元資料標籤:

@fileOverview 說明

標記說明整個檔案的 JSDoc 註解。例如

/**
 * @fileOverview Various tool functions.
 * @author <a href="mailto:jd@example.com">John Doe</a>
 * @version 3.1.2
 */
@author
參照撰寫所記錄實體的人員。
@deprecated
指出實體不再受支援。建議記錄應改用什麼。
@example

包含說明如何使用所提供實體的程式碼範例

/**
 * @example
 * var str = 'abc';
 * console.log(repeat(str, 3)); // abcabcabc
 */

連結的基本標籤如下

@see

指向相關資源

/**
 * @see MyConstructor#myMethod
 * @see The <a href="http://example.com">Example Project</a>.
 */
{@link ...}
作用類似於 @see,但可用於其他標籤中。
@requires resourceDescription
指出記錄實體所需的資源。資源說明為名稱路徑或自然語言說明。

版本標籤包括以下內容

@version versionNumber

指出記錄實體的版本。例如

@version 10.3.1
@since versionNumber

指出記錄實體自哪個版本開始提供。例如

@since 10.2.0

記錄函式和方法

對於函式和方法,您可以記錄參數、傳回值和它們可能會引發的例外狀況:

@param {paramType} paramName 說明

說明名稱為 paramName參數。類型和說明為選用。以下是一些範例:

@param str The string to repeat.
@param {string} str
@param {string} str The string to repeat.

進階功能

  • 選用參數

    @param {number} [times] The number of times is optional.
  • 具有預設值的選用參數

    @param {number} [times=1] The number of times is optional.
@returns {returnType} 說明
描述函數或方法的回傳值。類型或描述可以省略。
@throws {exceptionType} description
描述函數或方法執行期間可能引發的例外。類型或描述可以省略。

內嵌類型資訊(「內嵌文件註解」)

兩種提供參數和回傳值類型資訊的方法。首先,您可以將類型註解新增至 @param@returns

/**
 * @param {String} name
 * @returns {Object}
 */
function getPerson(name) {
}

其次,您可以內嵌類型資訊

function getPerson(/**String*/ name) /**Object*/ {
}

文件化變數、參數和實例屬性

下列標籤 用於文件化變數、參數和實例屬性:

@type {typeName}

文件化變數的類型為何?例如:

/** @type {number} */
var carCounter = 0;

此標籤也可用于文件化函數的回傳類型,但 @returns 在此情況下較佳。

@constant

表示文件化變數具有常數值的旗標。

/** @constant */
var FORD = 'Ford';
@property {propType} propKey description

在建構函數註解中文件化 實例屬性。例如:

/**
 * @constructor
 * @property {string} name The name of the person.
 */
function Person(name) {
    this.name = name;
}

或者,實例屬性可以如下文件化

/**
 * @class
 */
function Person(name) {
    /**
     * The name of the person.
     * @type {string}
     */
    this.name = name;
}

使用哪一種樣式取決於個人喜好。

@default defaultValue

參數或實例屬性的預設值為何?例如:

/** @constructor */
function Page(title) {
    /**
     * @default 'Untitled'
     */
     this.title = title || 'Untitled';
}

文件化類別

JSDoc 區分 類別和建構函數。前者概念較像類型,而建構函數是實作類別的方法之一。JavaScript 定義類別的內建方法有限,因此有許多 API 可協助執行此任務。這些 API 差異很大,因此您必須協助 JSDoc 找出發生了什麼事。下列標籤可讓您執行此操作:

@constructor
將函數標記為建構函數。
@class
將變數或函數標記為類別。在後一種情況下,@class@constructor 的同義詞。
@constructs
記錄方法設定實例資料。如果存在此方法,則類別會文件化在此處。
@lends namePath

指定下列物件文字對應哪個類別。有兩種對應方式。

  • @lends Person#:物件文字對應 Person 的實例成員。
  • @lends Person:物件文字對應 Person 的靜態成員。
@memberof parentNamePath
已記錄的實體是指定物件的成員。應用於物件文字的 @lends MyClass#,其效果等同於使用 @memberof MyClass# 標記該文字的每個屬性。

定義類別最常見的方式有:透過建構函式、透過物件文字,以及透過具有 @constructs 方法的物件文字。

透過建構函式定義類別

若要透過建構函式定義類別,您必須標記建構函式;否則,它不會被記錄為類別。 光靠大寫並不足以標記函式為建構函式:

/**
 * A class for managing persons.
 * @constructor
 */
function Person(name) {
}

透過物件文字定義類別

若要透過物件文字定義類別,您需要兩個標記。首先,您需要告訴 JSDoc 給定的變數包含類別。其次,您需要標記物件文字為定義類別。您可以透過 @lends 標籤執行後者:

/**
 * A class for managing persons.
 * @class
 */
var Person = makeClass(
    /** @lends Person# */
    {
        say: function(message) {
            return 'This person says: ' + message;
        }
    }
);

透過具有 @constructs 方法的物件文字定義類別

如果物件文字具有 @constructs 方法,您需要告訴 JSDoc,以便它可以找到實例屬性的文件。類別的文件會移至該方法:

var Person = makeClass(
    /** @lends Person# */
    {
        /**
         * A class for managing persons.
         * @constructs
         */
        initialize: function(name) {
            this.name = name;
        },
        say: function(message) {
            return this.name + ' says: ' + message;
        }
    }
);

如果您省略 @lends,您必須指定方法所屬的類別

var Person = makeClass({
        /**
         * A class for managing persons.
         * @constructs Person
         */
        initialize: function(name) {
            this.name = name;
        },
        /** @memberof Person# */
        say: function(message) {
            return this.name + ' says: ' + message;
        }
    }
);

子類化

JavaScript 沒有內建的子類化支援。當您在程式碼中進行子類化(不論是手動或透過函式庫),您必須告訴 JSDoc 正在發生什麼事:

@extends namePath

表示已記錄的類別是另一個類別的子類別。例如

/**
 * @constructor
 * @extends Person
 */
function Programmer(name) {
    Person.call(this, name);
    ...
}
// Remaining code for subclassing omitted

其他有用的標籤

所有這些標籤都記錄在 JSDoc 網站

  • 模組化:@module@exports@namespace
  • 自訂類型(針對虛擬實體,例如您可以記錄其簽章的回呼):@typedef@callback
  • 法律事項:@copyright@license
  • 各種物件:@mixin@enum


[23] JSDoc 網站是本章的主要來源;有些範例取自該網站。

下一頁:30. 函式庫