簡體   English   中英

如何獲取閉包編譯器以正確檢查JavaScript中構造函數的屬性

[英]How to get closure compiler to properly check the properties of a constructor in javascript

我不明白如何獲取適用於JavaScript的Google閉包編譯器以正確識別構造函數的屬性。 例如,在下面的代碼中,我不知道在第27行中賦予'cls'的類型是什么,以便編譯器不會產生以下(我認為是錯誤的)錯誤:

foo.js:29:警告-屬性聲明永遠不會在cls cls.say();上定義 ^

通過閱讀文檔,看來我應該像在25中那樣做。有人可以幫忙嗎? 謝謝,

 1  /**
 2   * @interface
 3   **/
 4  function Sayer() {}
 5  Sayer.prototype.say = function() {};
 6  Sayer.say = function() {};
 7  
 8  /**
 9   * @constructor
10   * @implements {Sayer}
11   **/
12  function A() {}
13  A.say = function() { console.log('A factory'); };
14  A.prototype.say = function() { console.log('Am an A'); }
15  
16  /**
17   * @constructor
18   * @implements {Sayer}
19   **/
20  function B() {}
21  B.say = function() { console.log('B factory'); };
22  B.prototype.say = function() { console.log('Am an B'); };
23  
24  /**
25   * @param {function(new:Sayer)} cls
26   **/
27  function makeSayer(cls) {
28      var obj = new cls();
29      cls.say();
30      obj.say();
31  }
32  
33  makeSayer(A);
34  makeSayer(B);

接口上的“ Sayer.say”將被忽略。

您是否正在為Closure的高級模式做准備? 在高級模式下,“ A.say”和“ B.say”被重命名為“ A $ say”和“ B $ say”,類型檢查會期望這一點並適當地抱怨它(不會有方法A.say )。

您可以通過間接添加來避免崩潰:

function addSay(sayer, fn) {
  sayer.say = fn;
}

我想您可以通過添加如下行來避免類型警告:

Function.prototype.say;

但是我不確定這就是您想要的。

您可以避免麻煩,並將其添加到原型中,然后調用它:

A.prototype.classSay = function () {};  

問題是一個接口(上定義的方法之間的區別A.say )對上的一個接口的原型(定義的方法A.prototype.say )。 在Closure的類型系統中, @interface標記提供以下保證:

任何實現接口的類都必須實現接口原型上定義的所有方法和屬性。

注意,它只關心原型上的方法。 它不在乎接口本身的方法。

假設您創建一個實現Sayer的新類C 關閉將確保您定義C.prototype.say 但是,您可以跳過C.say 您不需要實施它。 以下是一個完全有效的Sayer

/**
 * @constructor
 * @implements {Sayer}
 */
function C() {}
C.prototype.say = function() { console.log('Am a C'); }

由於這是有效的Sayer ,因此應該安全地調用makeSayer(C) 現在很清楚,為什么您對makeSayer的定義不正確。 它假定已定義cls.say ,但Closure不提供此類保證。 關閉可以發現問題,並為您提供適當的錯誤消息。

那你該怎么辦?

如果要遵循標准的面向對象方法,則可能需要兩個接口,一個用於工廠SayerFactory ,一個用於其創建的對象Say 您所有的方法都將成為原型中定義的方法,而Closure將為您進行所有檢查。

但是,如果您喜歡在構造函數中使用say方法的想法,則可以嘗試使用鴨子類型來強制執行factory方法。 就像是:

/**
 * @param {{say:function():Sayer}} cls
 */
function makeSayer(cls) {
  ...
}

當然,如果您需要定義不止一種方法,那么鴨子輸入法將無法很好地擴展。 對於每種定義的方法,類型簽名將變得越來越大。

祝好運!

暫無
暫無

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

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