An introduction to JSDoc
Join the DZone community and get the full member experience.
Join For FreeJSDoc is the de facto standard for documenting JavaScript code. You need to know at least its syntax (which is also used by many other tools) if you publish code. Alas, documentation is still scarce, but this post can help – it shows you how to run JSDoc and how its syntax works. (The JSDoc wiki [2] is the main source of this post, some examples are borrowed from it.)
As a tool, JSDoc takes JavaScript code with special /** */ comments and produces HTML documentation for it. For example: Given the following code.
/** @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); } };The generated HTML looks as follows in a web browser: This post begins with a quick start, so can try out JSDoc immediately if you are impatient. Afterwards, more background information is given.
1. Quick start
For the steps described below, you need to have Java installed. JSDoc includes the shell script jsrun.sh that requires Unix (including OS X and Linux) to run. But it should be easy to translate that script to a Windows batch file.- Download the latest jsdoc_toolkit. Unpack the archive into, say, $HOME/jsdoc-toolkit.
- Make the script $HOME/jsdoc-toolkit/jsrun.sh executable and tell it where to look for the JSDoc binary and the template (which controls what the result looks like).
JSDOCDIR="$HOME/local/jsdoc-toolkit" JSDOCTEMPLATEDIR="$JSDOCDIR/templates/jsdoc"
Now you can move the script anywhere you want to, e.g. a bin/ directory. For the purpose of this demonstration, we don’t move the script. - Use jsrun.sh on a directory of JavaScript files:
$HOME/jsdoc-toolkit/jsrun.sh -d=$HOME/doc $HOME/js
- Input: $HOME/js – a directory of JavaScript files (see below for an example).
- Output: $HOME/doc – where to write the generated files.
$HOME/doc +-- files.html +-- index.html +-- symbols +-- _global_.html +-- src ¦ +-- util.js.html +-- util.html
2. Introduction: What is JSDoc?
It’s a common programming problem: You have written JavaScript code that is to be used by others and need a nice-looking HTML documentation of its API. Java has pioneered this domain via its JavaDoc tool. The quasi-standard in the JavaScript world is JSDoc. As seen above, you document an entity by putting before it a special comment that starts with two asterisks.Templates. In order to output anything, JSDoc always needs a template, a mix of JavaScript and specially marked-up HTML that tells it how to translate the parsed documentation to HTML. JSDoc comes with a built-in template, but there are others that you can download [3].
2.1. Terminology and conventions of JSDoc
- Doclet: JSDoc calls its comments doclets which clashes with JavaDoc terminology where such comments are called doc comments and a doclet is similar to a JSDoc template, but written in Java.
- Variable: The term variable in JSDoc often refers to all documentable entities which include global variables, object properties, and inner members.
- Instance properties: In JavaScript one typically puts methods into a prototype to share them with all instances of a class, while fields (non-function-valued properties) are put into each instance. JSDoc conflates shared properties and per-instance properties and calls them instance properties.
- Class properties, static properties: are properties of classes, usually of constructor functions. For example, Object.create is a class property of Object.
- Inner members: An inner member is data nested inside a function.
Most relevant for documentation is instance-private data nested inside a
constructor function.
function MyClass() { var privateCounter = 0; // an inner member this.inc = function() { // an instance property privateCounter++; }; }
2.2. Syntax
Let’s review the comment shown at the beginning:/** * 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} */This demonstrates some of the JSDoc syntax which consists of the following pieces.
- JSDoc comment: is a JavaScript block comment whose first character is an asterisk. This creates the illusion that the token /** starts such a comment.
- Tags: Comments are structured by starting lines with tags, keywords that are prefixed with an @ symbol. @param is an example above.
- HTML: You can freely use HTML in JSDoc comments; for example, <tt> to display a word in a monospaced font.
- Type annotations: You can document the type of a value by
putting the type name in braces after the appropriate tags. Variations:
Single type: @param {string} name Multiple types: @param {string|number} idCode Arrays of a type: @param {string[]} names - Name paths: are used to refer to variables inside JSDoc comments. The syntax of such paths is as follows.
myFunction MyConstructor MyConstructor.classProperty MyConstructor#instanceProperty MyConstructor-innerMember
2.3. A word on types
There are two kinds of values in JavaScript: primitives and objects [7].- Primitive types: boolean, number, string. The values undefined and null are also considered primitive.
- Object types: All other types are object types, including arrays and functions.
- The wrapper type of boolean is Boolean.
- The wrapper type of number is Number.
- The wrapper type of string is String.
- Primitive value p: via typeof p.
> typeof "" 'string'
Compare: an instance of the wrapper type is an object.> typeof new String() 'object'
- Object value o: via o.constructor.name. Example:
> new String().constructor.name 'String'
3. Basic tags
Meta-data:- @fileOverview: marks a JSDoc comment that describes the whole file.
- @author: Who has written the variable being documented?
- @deprecated: indicates that the variable is not supported, any more. It is a good practice to document what to use instead.
- @example: contains a code example, illustrating how the given entity should be used.
/** * @example * var str = "abc"; * console.log(repeat(str, 3)); // abcabcabc */
- @see: points to a related resource.
/** * @see MyClass#myInstanceMethod * @see The <a href="http://example.com">Example Project</a>. */
- {@link ...}: works like @see, but can be used inside other tags.
- @requires resourceDescription: a resource that the documented entity needs. The resource description is either a name path or a natural language description.
- @version versionNumber: indicates the version of the documented entity. Example:
@version 10.3.1
- @since versionNumber: indicates since which version the documented entity has been available. Example:
@since 10.2.0
4. Documenting functions and methods
For functions and methods, one can document parameters, return values, and exceptions they might throw.- @param {paramType} paramName description: describes the parameter whose name is paramName. Type and description are optional. Examples:
@param str @param str The string to repeat. @param {string} str @param {string} str The string to repeat.
Advanced features:- Optional parameter:
@param {number} [times] The number of times is optional.
- Optional parameter with default value:
@param {number} [times=1] The number of times is optional.
- Optional parameter:
- @returns {returnType} description: describes the return value of the function or method. Either type or description can be omitted.
- @throws {exceptionType} description: describes an exception that might be thrown during the execution of the function or method. Either type or description can be omitted.
4.1. Inline type information (“inline doc comments”)
There are two ways of providing type information for parameters and return values. First, you can add a type annotation to @param and @returns./** * @param {String} name * @returns {Object} */ function getPerson(name) { }Second, you can inline the type information:
function getPerson(/**String*/ name) /**Object*/ { }
5. Documenting variables and fields
Fields are properties with non-function values. Because instance fields are often created inside a constructor, you have to document them there.- @type {typeName}: What type does the documented variable have? Example:
/** @constructor */ function Car(make, owner) { /** @type {string} */ this.make = make; /** @type {Person} */ this.owner = owner; } @type {Person}
This tag can also be used to document the return type of functions, but @returns is preferable in this case. - @constant: A flag that indicates that the documented variable has a constant value.
- @default defaultValue: What is the default value of a variable? Example:
/** @constructor */ function Page(title) { /** * @default "Untitled" */ this.title = title || "Untitled"; }
- @property {propType} propName description: Document an instance property in the class comment. Example:
/** * @class * @property {string} name The name of the person. */ function Person(name) { this.name = name; }
Without this tag, instance properties are documented as follows./** * @class */ function Person(name) { /** * The name of the person. * @type {string} */ this.name = name; }
Which one of those styles to use is a matter of taste. @property does introduce redundancies, though.
6. Documenting classes
JavaScript’s built-in means for defining classes are weak, which is why there are many APIs that help with this task [5]. These APIs differ, often radically, so you have to help JSDoc with figuring out what is going on. There are three basic ways of defining a class:- Constructor function: You must mark a constructor
function, otherwise it will not be documented as a class. That is,
capitalization alone does not mark a function as a constructor.
/** * @constructor */ function Person(name) { }
@class is a synonym for @constructor, but it also allows you to describe the class – as opposed to the function setting up an instance (see tag documentation below for an example). - API call and object literal: You need two markers. First,
you need to tell JSDoc that a given variable holds a class. Second, you
need to mark an object literal as defining a class. The latter is done
via the @lends tag.
/** @class */ var Person = makeClass( /** @lends Person# */ { say: function(message) { return "This person says: " + message; } } );
- API call and object literal with a constructor method: If
one of the methods in an object literal performs the task of a
constructor (setting up instance data, [8]), you need to mark it as such
so that fields are found by JSDoc. Then the documentation of the class
moves to that method.
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; } } );
- @constructor: marks a function as a constructor.
- @class: marks a variable as a class or a function as a
constructor. Can be used in a constructor comment to separate the
description of the constructor (first line below) from the description
of the class (second line below).
/** * Creates a new instance of class Person. * @class Represents a person. */ Person = function() { }
- @constructs: marks a method in an object literal as taking up the duties of a constructor. That is, setting up instance data. In such a case, the class must be documented there. Works in tandem with @lends.
- @lends namePath: specifies to which class the following object literal contributes. There are two ways of contributing.
- @lends Person# – the object literal contributes instance properties to Person.
- @lends Person – the object literal contributes class properties to Person.
6.1. Inheritance, namespacing
JavaScript has no simple support for subclassing and no real namespaces [6]. You thus have to help JSDoc see what is going on when you are using work-arounds.- @extends namePath: indicates that the documented class is the subclass of another one. Example:
/** * @constructor * @extends Person */ function Programmer(name) { Person.call(this, name); ... } // Remaining code for subclassing omitted
- @augments: a synonym for @extends.
- @namespace: One can use objects to simulate namespaces in JavaScript. This tag marks such objects. Example:
/** @namespace */ var util = { ... };
7. Meta-tags
Meta-tags are tags that are added to several variables. You put them in a comment that starts with “/**#@+”. They are then added to all variables until JSDoc encounters the closing comment “/**#@-*/”. Example:/**#@+ * @private * @memberOf Foo */ function baz() {} function zop() {} function pez() {} /**#@-*/
8. Rarely used tags
- @ignore: ignore a variable. Note that variables without /** comments are ignored, anyway.
- @borrows otherNamePath as this.propName: A variable is just a reference to somewhere else; it is documented there. Example:
/** * @constructor * @borrows Remote#transfer as this.send */ function SpecialWriter() { this.send = Remote.prototype.transfer; }
- @description text: Provide a description, the same as all of the text before the first tag.
Name and membership:
Tag Mark variable as @function function @field non-function value @public public (especially inner variables) @private private @inner inner and thus also private @static accessible without instantiation
- @name namePath: override the parsed name and use the given name, instead.
- @memberOf parentNamePath: the documented variable is a member of the specified object.
9. Related reading
- jsdoc-toolkit - A documentation generator for JavaScript: JSDoc homepage on Google Code. Includes a link to the downloads.
- JSDoc wiki: the official documentation of JSDoc and source of this post.
- JSDoc wiki – TemplateGallery: lists available JSDoc templates.
- JSDoc wiki – TagReference: a handy cheat-sheet for JSDoc tags.
- Lightweight JavaScript inheritance APIs
- Modules and namespaces in JavaScript
- JavaScript values: not everything is an object
- Prototypes as classes – an introduction to JavaScript inheritance
Opinions expressed by DZone contributors are their own.
Comments