簡體   English   中英

JSDoc:我如何記錄`var self = this;`?

[英]JSDoc: How do I document `var self = this;`?

只要您使用this關鍵字,JSDoc 就非常擅長獲取在類上定義的方法和屬性,例如:

/** @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作為 Member 和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 member 或任何方法。

我已經看到您可以@memberof使用@memberof手動將每個成員和方法附加到類,但這真的很冗長,我想知道是否有辦法告訴 JSDoc self指的是類。

(順便說一句,我正在使用 JSDoc 3.4,以防萬一。)

@alias注釋可用於告訴 JSDoc 將self視為對類的引用。 實際上,從技術上講,您需要將self別名為類的原型,而不僅僅是類本身的名稱(以我不完全理解的方式破壞了東西)。 為此,您需要將@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;

// ...

您正在使這個(請原諒雙關語)變得比它需要的更復雜。 你的設計有很多問題。

  1. 您不需要使用this來設置原型。 我非常喜歡像這樣將對象InstantiationInitialization范式分開:

     /** @class */ function Person() {} Person.prototype = { /** This person's name * @return {Person} */ init: function(name) { this.name = name; return this; }, };
  2. Greet已經在一個對象上工作,你不需要傳入第二個對象:

     /** Greet someone */ greet: function() { return 'Hey there, '+this.name; },

    這也簡化了logGreeting

     /** Log a greeting to the browser console */ logGreeting: function() { console.log(this.greet()); },
  3. 但是,假設您確實想將第二個對象(人)傳遞給您的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 };
  4. 您不應該使用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));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM