JSDoc:如何记录 `var self = this;`?
JSDoc: How do I document `var self = this;`?
只要您使用 this
关键字,JSDoc 就非常擅长获取 class 上定义的方法和属性,例如:
/** @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));
};
}
这将生成带有 "Class Person" 页面的文档,其中 name
作为成员,greet()
和 logGreeting()
作为方法。
但是当我遇到需要使用 self = this
模式的复杂情况时,事情就开始崩溃了:
/** @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);
};
}
此示例生成一个 Class Person
页面,但它没有 name
成员或任何方法。
我看到你可以到处使用 @memberof
手动将每个成员和方法附加到 class,但这真的很冗长,我想知道是否有告诉 JSDoc self
指的是 class.
的方法
(顺便说一句,我正在使用 JSDoc 3.4,以防万一。)
@alias
注释可用于告诉 JSDoc 将 self
视为对 class 的引用。实际上,从技术上讲,您需要为 class 的 原型 添加别名 self
,而不仅仅是 class 本身的名称(这会破坏内容以我不完全理解的方式)。为此,您需要将 @alias
设置为 Person#
1:
/** @class */
function Person(name) {
/** @alias Person# */
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);
};
}
1: 从技术上讲,Person#
等同于 Person.prototype
,因为尾随 #
指的是对象的原型(据我了解它;开放纠正)。话虽这么说,this
实际上指的是一个实例,与原型不相同,所以我建议不要使用这种表示法,因为它会使注释更加混乱。幸运的是,原型方法和真正的实例方法之间的 JSDoc 输出没有区别,所以不用太担心 Person#
表示法。
工作相同的备选方案,为了完整性而包括在内,但可能应该避免:
// ...
/** @alias Person.prototype */
var self = this;
// ...
你让这个(请原谅双关语)变得比它需要的更复杂。你的设计有很多问题。
您不需要使用this
来设置原型。我非常喜欢像这样将对象 Instantiation
与 Initialization
范式分开:
/** @class */
function Person() {}
Person.prototype =
{
/** This person's name
* @return {Person}
*/
init: function(name)
{
this.name = name;
return this;
},
};
问候已经在一个对象上工作,你不需要传入第二个对象:
/** Greet someone */
greet: function() {
return 'Hey there, '+this.name;
},
这也简化了 logGreeting
:
/** Log a greeting to the browser console */
logGreeting: function() {
console.log(this.greet());
},
但是,假设您确实想要将第二个对象(人)传递给您的logGreeting
它错误地传递了 Class
而不是 Object
。应该是这样的:
/** 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)); // BUG: was Person instead of person
};
您不应该使用 self
来设置原型——您首先误用了使用 self
的原因:它们用于需要引用对象的回调。
比如我们添加一个人改名时的回调:
rename: function(newName) {
var self = this;
var cbRename = function() {
self.onRename( self.name, newName ); // Why self is needed
self.name = newName;
};
setTimeout( cbRename, 1 );
},
/** Callback triggered on rename */
onRename: function(oldName,newName) {
console.log( "The person formally known as: '" + oldName + "'" );
console.log( "Is now known as: '" + newName + "'" );
},
在示例中将所有内容放在一起:
/** @class */
function Person() {}
Person.prototype =
{
/** This person's name
* @return {Person}
*/
init: function(name)
{
this.name = name;
return this;
},
/** Greet someone */
greet: function() {
return 'Hey there, '+this.name;
},
/** Log a greeting to the browser console */
logGreeting: function() {
console.log(this.greet());
},
rename: function(newName) {
var self = this;
var cbRename = function() {
self.onRename( self.name, newName );
self.name = newName;
};
setTimeout( cbRename, 1 );
},
/** Callback triggered on rename */
onRename: function(oldName,newName) {
console.log( "The person formally known as: '" + oldName + "'" );
console.log( "Is now known as: '" + newName + "'" );
},
};
var alice = new Person().init( 'Alice' );
console.log( alice );
alice.logGreeting();
alice.rename( 'Bob' );
生成这个 JSdoc3 html:
<div id="main">
<h1 class="page-title">Class: Person</h1>
<section>
<header>
<h2>Person</h2>
</header>
<article>
<div class="container-overview">
<hr>
<h4 class="name" id="Person"><span class="type-signature"></span>new Person<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line2">line 2</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<hr>
<h4 class="name" id="greet"><span class="type-signature"></span>greet<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Greet someone
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line17">line 17</a>
</li></ul></dd>
</dl>
<hr>
<h4 class="name" id="init"><span class="type-signature"></span>init<span class="signature">()</span><span class="type-signature"> → {<a href="Person.html">Person</a>}</span></h4>
<div class="description">
This person's name
return {Person}
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line9">line 9</a>
</li></ul></dd>
</dl>
<hr>
<h4 class="name" id="logGreeting"><span class="type-signature"></span>logGreeting<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Log a greeting to the browser console
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<hr>
<h4 class="name" id="onRename"><span class="type-signature"></span>onRename<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Callback triggered on rename
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line38">line 38</a>
</li></ul></dd>
</dl>
</article>
</section>
</div>
为什么使用变量接收 this
而不是使用带箭头函数的 this
?
/** @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));
};
/** Log a greeting to the browser console after some delay */
this.logGreetingDelayed = function(person, delay) {
setTimeout(() => this.logGreeting(person), delay);
};
}
如果您想记录 this
(例如使用私有方法),您可以使用 JSDoc @this
:
/** @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) {
privateLogGreeting.call(this, person);
};
/** Log a greeting to the browser console after some delay */
this.logGreetingDelayed = function(person, delay) {
setTimeout(() => this.logGreeting(person), delay);
};
}
//Private method
/**
* @this Person
* @param {Person} person
*/
function privateLogGreeting(person) {
console.log(this.greet(person));
}
只要您使用 this
关键字,JSDoc 就非常擅长获取 class 上定义的方法和属性,例如:
/** @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));
};
}
这将生成带有 "Class Person" 页面的文档,其中 name
作为成员,greet()
和 logGreeting()
作为方法。
但是当我遇到需要使用 self = this
模式的复杂情况时,事情就开始崩溃了:
/** @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);
};
}
此示例生成一个 Class Person
页面,但它没有 name
成员或任何方法。
我看到你可以到处使用 @memberof
手动将每个成员和方法附加到 class,但这真的很冗长,我想知道是否有告诉 JSDoc self
指的是 class.
(顺便说一句,我正在使用 JSDoc 3.4,以防万一。)
@alias
注释可用于告诉 JSDoc 将 self
视为对 class 的引用。实际上,从技术上讲,您需要为 class 的 原型 添加别名 self
,而不仅仅是 class 本身的名称(这会破坏内容以我不完全理解的方式)。为此,您需要将 @alias
设置为 Person#
1:
/** @class */
function Person(name) {
/** @alias Person# */
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);
};
}
1: 从技术上讲,Person#
等同于 Person.prototype
,因为尾随 #
指的是对象的原型(据我了解它;开放纠正)。话虽这么说,this
实际上指的是一个实例,与原型不相同,所以我建议不要使用这种表示法,因为它会使注释更加混乱。幸运的是,原型方法和真正的实例方法之间的 JSDoc 输出没有区别,所以不用太担心 Person#
表示法。
工作相同的备选方案,为了完整性而包括在内,但可能应该避免:
// ...
/** @alias Person.prototype */
var self = this;
// ...
你让这个(请原谅双关语)变得比它需要的更复杂。你的设计有很多问题。
您不需要使用
this
来设置原型。我非常喜欢像这样将对象Instantiation
与Initialization
范式分开:/** @class */ function Person() {} Person.prototype = { /** This person's name * @return {Person} */ init: function(name) { this.name = name; return this; }, };
问候已经在一个对象上工作,你不需要传入第二个对象:
/** Greet someone */ greet: function() { return 'Hey there, '+this.name; },
这也简化了
logGreeting
:/** Log a greeting to the browser console */ logGreeting: function() { console.log(this.greet()); },
但是,假设您确实想要将第二个对象(人)传递给您的
logGreeting
它错误地传递了Class
而不是Object
。应该是这样的:/** 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)); // BUG: was Person instead of person };
您不应该使用
self
来设置原型——您首先误用了使用self
的原因:它们用于需要引用对象的回调。
比如我们添加一个人改名时的回调:
rename: function(newName) {
var self = this;
var cbRename = function() {
self.onRename( self.name, newName ); // Why self is needed
self.name = newName;
};
setTimeout( cbRename, 1 );
},
/** Callback triggered on rename */
onRename: function(oldName,newName) {
console.log( "The person formally known as: '" + oldName + "'" );
console.log( "Is now known as: '" + newName + "'" );
},
在示例中将所有内容放在一起:
/** @class */
function Person() {}
Person.prototype =
{
/** This person's name
* @return {Person}
*/
init: function(name)
{
this.name = name;
return this;
},
/** Greet someone */
greet: function() {
return 'Hey there, '+this.name;
},
/** Log a greeting to the browser console */
logGreeting: function() {
console.log(this.greet());
},
rename: function(newName) {
var self = this;
var cbRename = function() {
self.onRename( self.name, newName );
self.name = newName;
};
setTimeout( cbRename, 1 );
},
/** Callback triggered on rename */
onRename: function(oldName,newName) {
console.log( "The person formally known as: '" + oldName + "'" );
console.log( "Is now known as: '" + newName + "'" );
},
};
var alice = new Person().init( 'Alice' );
console.log( alice );
alice.logGreeting();
alice.rename( 'Bob' );
生成这个 JSdoc3 html:
<div id="main">
<h1 class="page-title">Class: Person</h1>
<section>
<header>
<h2>Person</h2>
</header>
<article>
<div class="container-overview">
<hr>
<h4 class="name" id="Person"><span class="type-signature"></span>new Person<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line2">line 2</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<hr>
<h4 class="name" id="greet"><span class="type-signature"></span>greet<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Greet someone
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line17">line 17</a>
</li></ul></dd>
</dl>
<hr>
<h4 class="name" id="init"><span class="type-signature"></span>init<span class="signature">()</span><span class="type-signature"> → {<a href="Person.html">Person</a>}</span></h4>
<div class="description">
This person's name
return {Person}
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line9">line 9</a>
</li></ul></dd>
</dl>
<hr>
<h4 class="name" id="logGreeting"><span class="type-signature"></span>logGreeting<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Log a greeting to the browser console
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<hr>
<h4 class="name" id="onRename"><span class="type-signature"></span>onRename<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Callback triggered on rename
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="person.js.html">person.js</a>, <a href="person.js.html#line38">line 38</a>
</li></ul></dd>
</dl>
</article>
</section>
</div>
为什么使用变量接收 this
而不是使用带箭头函数的 this
?
/** @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));
};
/** Log a greeting to the browser console after some delay */
this.logGreetingDelayed = function(person, delay) {
setTimeout(() => this.logGreeting(person), delay);
};
}
如果您想记录 this
(例如使用私有方法),您可以使用 JSDoc @this
:
/** @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) {
privateLogGreeting.call(this, person);
};
/** Log a greeting to the browser console after some delay */
this.logGreetingDelayed = function(person, delay) {
setTimeout(() => this.logGreeting(person), delay);
};
}
//Private method
/**
* @this Person
* @param {Person} person
*/
function privateLogGreeting(person) {
console.log(this.greet(person));
}