JSDoc is great at picking up on methods and properties defined on a class as long as you use the this
keyword, e.g.:
/** @class */
function Person(name) {
/** This person's name */
this.name = name;
/** Greet someone */
this.greet = function(person) {
return 'Hey there, '+person.name;
};
/** Log a greeting to the browser console */
this.logGreeting = function(person) {
console.log(this.greet(Person));
};
}
This will generate docs with a “Class Person” page listing name
as a Member and greet()
and logGreeting()
as Methods.
But when I have a complex case where I need to use the self = this
pattern, things start to break:
/** @class */
function Person(name) {
var self = this;
/** This person's name */
self.name = name;
/** Greet someone */
self.greet = function(person) {
return 'Hey there, '+person.name;
};
/** Log a greeting to the browser console */
self.logGreeting = function(person) {
console.log(self.greet(Person));
};
/** Log a greeting to the browser console after some delay */
self.logGreetingDelayed = function(person, delay) {
setTimeout(function() { self.logGreeting(person); }, delay);
};
}
This example generates a Class Person
page, but it doesn’t have the name
member or any of the methods.
I’ve seen that you can use @memberof
all over the place to manually attach each member and method to the class, but this is really verbose, and I was wondering whether there’s a way to tell JSDoc that self
refers to the class.
(Btw, I’m using JSDoc 3.4, in case that’s important.)
Why use a variable to receive
this
instead to usethis
with arrow function?And if you want to document
this
(to use private methods for instance) you can use JSDoc@this
:The
@alias
annotation can be used to tell JSDoc to treatself
as a reference to the class. Actually, technically, you need to aliasself
to the class’s prototype, not just the name of the class itself (that breaks stuff in ways that I don’t fully understand). To do this you need to set@alias
toPerson#
1:1: Technically,
Person#
is equivalent toPerson.prototype
, since a trailing#
refers to an object’s prototype (as I understand it; open to correction). That being said,this
actually refers to an instance, which is not the same as the prototype, so I recommend against using this notation, since it makes the comments more confusing. Fortunately, there’s no difference in the JSDoc output between a prototype method and a true instance method, so don’t worry too much about thePerson#
notation.Alternative that works the same, included for completeness, but which should probably be avoided:
You are making this (pardon the pun) more complicated then it needs to be. There are numerous problems with your design.
You don’t need to use
this
to set prototypes. I greatly prefer to separate objectInstantiation
fromInitialization
paradigm like this:Greet already works on an object, you doesn’t need pass in a 2nd object:
This also simplifies
logGreeting
:However, assuming you do want to pass in a second object (person) to your
logGreeting
it is incorrectly passing aClass
and not anObject
. It should be this:You shouldn’t be using
self
to set prototypes — you’re mis-using the reason for usingself
in the first place: They are used for callbacks that need an object to refer to.For example, let’s add a callback when a person is renamed:
Putting it all together in an example:
Which generates this JSdoc3 html: