對於一些功能比較複雜的函數,須要將不少配置項做爲參數傳入,這時候傳統的位置參數表就不太方便了,由於對於配置項參數,咱們每每會設置默認值,但願使用者無需按順序傳入全部參數,而只要指明哪幾個參數須要特別配置。前端
好比一個簡單的字符串格式化函數,除了必需的傳入值 value
外,有三個配置項:git
indent
:縮進github
caseMode
:大小寫面試
callback
:轉換完成後的回調編程
前端代碼中應該如何定義呢?bash
咱們先看看用 JavaScript 的狀況。編程語言
若是咱們按照最原始的定義方法:函數
function transform(value, indent, caseMode, callback) {
...
}
複製代碼
那麼使用者就必須記住全部配置參數的位置,要是隻想設置 caseMode
,須要寫成以下尷尬的形式:spa
transform('someStr', undefined, 'upper')
複製代碼
事實上不少 JavaScript 內置函數就是採用的這種方式,使用者很難記住全部的位置參數,所以[1, 2, 3].map(parseInt)
纔會成爲「經典」面試題。code
不少現代編程語言,好比 Dart 或 Python ,增長了「命名參數」這一特性,解決了參數與參數名對應的問題:
transform('someStr', caseMode: 'upper')
複製代碼
JavaScript 沒有命名參數這一特性,早期實踐中每每經過「配置對象參數「的方式,達到相似的效果:
function transform(value, cfg) {
...
if(cfg.caseMode) ...
}
複製代碼
對象參數的缺點是源碼中 cfg
的配置項不夠直觀,默認值設置比較麻煩,類型檢查約束性不夠。
如今配合上 ES6 的解構賦值和函數默認值,直觀性和默認值能夠解決了:
function transform(value, {
indent = 2,
caseMode = 'upper',
callback,
} = {}) {
...
}
複製代碼
不過約束性仍是不夠,不能實現「必選參數」、「可選參數」的功能。
這時候就要 TypeScript 上場了。
除了類型檢查外,TypeScript 能夠對必選參數進行空值檢查,而後再經過?:
手動設置可選參數:
function transform(value: string, {
indent = 2,
caseMode = 'upper',
callback,
}:{
indent?: number,
caseMode?: string,
callback?: (rst: string) => void,
} = {}) {
...
}
複製代碼
這就是 TypeScript 中比較完整的一個列子,實現了命名參數、可選參數,參數默認值的功能,使用時:
transform('someStr', { caseMode: 'upper' })
複製代碼
在以上的定義中,「命名參數」用上了 {}: {}={}
的結構進行定義,格式上要分紅兩段,另外因爲本質上是個對象參數,外面仍是不能忘了大括號的,寫法略有些冗長,可是 TypeScript 的團隊 表示 因爲保留位置限制、表達式解析等種種緣由,目前不會加入真正的「命名參數」特性,所以目前只能這樣寫。