3

我一直搞不清楚了關於下面的代碼段很長的時間:什麼時候在關閉中使用typedef?

/** 
* Pair of width and height. 
* @param {string} width 
* @param {string} height 
* @constructor 
* @struct 
*/ 
var Pair = function(width, height) { 
    /** @type {string} */ 
    this.key = key; 
    /** @type {string} */ 
    this.value = value; 
}; 

VS

/** 
* @typedef {{width: string, height: string}} 
*/ 
var Pair; 

基本上我需要創建一個新的類型和高度困惑要使用哪一個時?

+1

我認爲一個很好的答案應該涵蓋typedef,record和interface之間的區別。 –

回答

2

哪一個要用?

這在某種程度上是個人喜好和編碼風格的問題。 Closure Compiler更傾向於使用類,接口,方法等在Java中找到的僞古典繼承模式,這與其他方法不同。見Michael Bolin的Inheritance Patterns in JavaScript

另請參閱Annotating JavaScript for the Closure Compiler它具有最簡潔的各種標籤的定義。

對於我自己,我使用僞古典繼承模式。因此,99%的時間我正在使用@constructor來定義類,這些類與new關鍵字一起使用。這些類也被標記爲@struct,因此它們具有固定的一組屬性和方法。大約80%的我的課程聲明他們@implement@interface,因爲這允許我使用接口類型,而不是綁定到特定的類實現。

偶爾我會用@typedef來定義一個對象,它有一些最小的屬性集合。對我來說,這種類型的對象通常沒有定義它的函數,它只是聚合一些屬性的一種方式。

下面是我的代碼示例:

/** A regular expression and the replacement string expression to be used in a 
* `String.replace()` command. 
* @typedef {{regex: !RegExp, replace: string}} 
* @private 
*/ 
Terminal.regexPair; 

我可以使用的typedef別處:

/** Set of regular expressions to apply to each command. 
* @type {!Array.<!Terminal.regexPair>} 
* @private 
*/ 
this.regexs_ = []; 

的優點是,它很容易使這種類型的東西:

/** Add regular expression and replacement string to be used by `String.replace()` 
* for transforming script commands before they are executed. 
* @param {!RegExp} regex regular expression for finding a name to transform 
* @param {string} replace the replacement string for use with `String.replace()` 
*/ 
Terminal.prototype.addRegex = function(regex, replace) { 
    this.regexs_.push({regex:regex, replace:replace}); 
}; 

請注意,我使用{regex:regex, replace:replace}創建了一個匿名對象,而不是使用new運營商。然而,編譯器正在檢查此對象是否具有由Terminal.regexPair定義的必需(最小)屬性集。

但是還有很多關於如何編寫JavaScript代碼的其他哲學。你當然可以定義一個需要具有指定簽名的函數的typedef。

相關問題