これは一般的な開発上の問題です。他の人が使用するJavaScriptコードを記述し、そのAPIの見た目も美しいHTMLドキュメントが必要になります。JavaScriptの世界でAPIドキュメントを生成するためのデファクトスタンダードツールはJSDocです。[23] これはJavaの類似ツールであるJavaDocをモデルにしています。
JSDocは/** */コメント(アスタリスクで始まる通常のブロックコメント)を含むJavaScriptコードを受け取り、HTMLドキュメントを生成します。たとえば、次のコードが与えられた場合:
/** @namespace */varutil={/*** 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;}returnnewArray(times+1).join(str);}};
生成されたHTMLは、Webブラウザで図29-1のように表示されます。
JSDocウェブサイトのReadmeには、このツールのインストール方法と呼び出し方法が説明されています。
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構文は、次の要素で構成されています。
/**トークンがそのようなコメントを開始するという錯覚が生まれます。@paramは、上記のコードの例です。<tt>は単語を等幅フォントで表示します。波括弧で囲んだ型名を使用して、エンティティの型をドキュメント化できます。バリエーションには以下が含まれます。
@param {string} name@param {string|number} idCode@param {string[]} namesJSDocコメント内では、いわゆる名前パスを使用してエンティティを参照します。このようなパスの構文は次のとおりです。
myFunction MyClass MyClass.staticMember MyClass#instanceMember
クラスは通常、(によって実装される)コンストラクタです。静的メンバーは、たとえばコンストラクタのプロパティです。JSDocでは、インスタンスメンバーを広く定義しています。これは、インスタンスを介してアクセスできるすべてのものを意味します。したがって、インスタンスメンバーには、インスタンスプロパティとプロトタイププロパティが含まれます。
以下は、基本的なメタデータタグです。
@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 リソースの説明
バージョン管理タグには、以下が含まれます。
@version バージョン番号
ドキュメント化されたエンティティのバージョンを示します。例えば
@version 10.3.1
@since バージョン番号
ドキュメント化されたエンティティが利用可能になったバージョンを示します。例えば
@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} 説明
パラメータと戻り値の型情報を提供するには、2つの方法があります。1つ目は、@paramと@returnsに型注釈を追加する方法です。
/*** @param {String} name* @returns {Object}*/functiongetPerson(name){}
2つ目は、型情報をインライン化する方法です。
functiongetPerson(/**String*/name)/**Object*/{}
次のタグは、変数、パラメータ、およびインスタンスプロパティのドキュメント化に使用されます。
@type {typeName}
ドキュメント化された変数はどのような型ですか?例えば:
/** @type {number} */varcarCounter=0;
このタグは、関数の戻り値の型をドキュメント化するためにも使用できますが、この場合は@returnsの方が適しています。
@constant
ドキュメント化された変数の値が定数であることを示すフラグ。
/** @constant */varFORD='Ford';
@property {propType} propKey 説明
コンストラクタコメントでインスタンスプロパティをドキュメント化します。例えば:
/*** @constructor* @property {string} name The name of the person.*/functionPerson(name){this.name=name;}
あるいは、インスタンスプロパティは次のようにドキュメント化できます。
/*** @class*/functionPerson(name){/*** The name of the person.* @type {string}*/this.name=name;}
どちらのスタイルを使用するかは、個人の好みによります。
@default デフォルト値
パラメータまたはインスタンスプロパティのデフォルト値は何ですか?例えば:
/** @constructor */functionPage(title){/*** @default 'Untitled'*/this.title=title||'Untitled';}
JSDocは、クラスとコンストラクタを区別します。前者の概念はどちらかというと型のようなもので、コンストラクタはクラスを実装する1つの方法です。JavaScriptのクラス定義の組み込み手段は限られているため、このタスクを支援する多くのAPIが存在します。これらのAPIは、多くの場合根本的に異なるため、JSDocが何が起こっているかを理解するのを助ける必要があります。次のタグを使用すると、それができます。
@constructor
@class
@classは@constructorの同義語です。@constructs
@lends 名前パス
次のオブジェクトリテラルがどのクラスに寄与するかを指定します。寄与するには2つの方法があります。
@lends Person#: オブジェクトリテラルはインスタンスメンバーをPersonに寄与します。@lends Person: オブジェクトリテラルは静的メンバーをPersonに寄与します。@memberof 親名前パス
@lends MyClass#は、そのリテラルの各プロパティに@memberof MyClass#をマークするのと同じ効果があります。クラスを定義する最も一般的な方法は、コンストラクタ関数、オブジェクトリテラル、および@constructsメソッドを持つオブジェクトリテラルを使用することです。
コンストラクタ関数を使用してクラスを定義するには、コンストラクタ関数をマークする必要があります。そうしないと、クラスとしてドキュメント化されません。大文字化だけでは、関数がコンストラクタとしてマークされません。
/*** A class for managing persons.* @constructor*/functionPerson(name){}
オブジェクトリテラルを使用してクラスを定義するには、2つのマーカーが必要です。まず、JSDocに、特定の変数がクラスを保持していることを伝える必要があります。次に、オブジェクトリテラルをクラスを定義するものとしてマークする必要があります。@lendsタグを使用して後者を実行します。
/*** A class for managing persons.* @class*/varPerson=makeClass(/** @lends Person# */{say:function(message){return'This person says: '+message;}});
オブジェクトリテラルに@constructsメソッドがある場合、JSDocにそのことを知らせる必要があります。そうすることで、インスタンスプロパティのドキュメントを見つけることができます。クラスのドキュメントはそのメソッドに移動します。
varPerson=makeClass(/** @lends Person# */{/*** A class for managing persons.* @constructs*/initialize:function(name){this.name=name;},say:function(message){returnthis.name+' says: '+message;}});
@lendsを省略した場合、メソッドが属するクラスを指定する必要があります。
varPerson=makeClass({/*** A class for managing persons.* @constructs Person*/initialize:function(name){this.name=name;},/** @memberof Person# */say:function(message){returnthis.name+' says: '+message;}});
JavaScriptには、サブクラス化の組み込みサポートがありません。コードでサブクラス化する場合(手動で行うか、ライブラリを介して行うかにかかわらず)、JSDocに何が起こっているかを伝える必要があります。
@extends 名前パス
ドキュメント化されたクラスが別のクラスのサブクラスであることを示します。例えば
/*** @constructor* @extends Person*/functionProgrammer(name){Person.call(this,name);...}// Remaining code for subclassing omitted
これらのタグはすべて、JSDocウェブサイトに記載されています。