摘要:所以編輯器就會使用一個在中經常出現用來標識任意類型的關鍵字來描述函數的參數以及返回值。描述類型的返回值處理現在這個年代,基本上已經普及開來,所以很多函數的返回值可能并不是結果,而是一個。
工作了四年多,基本上都在圍繞著 JavaScript 做事情。作用
寫的代碼多了,看的代碼也多了,由衷的覺得,寫出別人看不懂的代碼并不是什么能力,寫出所有人都能讀懂的代碼,才是真的牛X。
眾所周知, JavaScript 是一個弱類型的腳本語言,這就意味著,從編輯器中并不能直觀的看出這段代碼的作用是什么,有些事情只有等到代碼真正的運行起來才能夠確定。
所以為了解決大型項目中 JavaScript 維護成本高的問題,前段時間我們團隊開始使用 TypeScript,但是由前幾年所積累下來的代碼,并不是說改立馬都能全部改完的,所以這個重構將是一個漫長的過程。
在重構同時我們還是需要繼續維護原有的 JavaScript 項目的,而 JSDoc 恰好是一個中間過渡的方案,可以讓我們以注釋的形式來降低 JavaScript 項目的維護難度,提升可讀性。
本人使用的是 vs code 編輯器,內置了對 jsdoc 的各種支持,同時還會根據部分常量,語法來推測出對應的類型
可以很方便的在編輯器中看到效果,所以下面所有示例都是基于 vscode 來做的。
首先,JSDoc 并不會對源碼產生任何的影響,所有的內容都是寫在注釋里邊的。
所以并不需要擔心 JSDoc 會對你的程序造成什么負面影響。
可以先來看一個普通的 JavaScript 文件在編輯器中的展示效果:
很顯而易見的,編輯器也不能夠確定這個函數究竟是什么含義,因為任何類型的兩個參數都可以進行相加。
所以編輯器就會使用一個在 TypeScript 中經常出現用來標識任意類型的 any 關鍵字來描述函數的參數以及返回值。
而這種情況下我們可以很簡單的使用 JSDoc 來手動描述這個函數的作用:
實際上有些函數是需要手動指定@return {TYPE}來確定函數返回值類型的,但因為我們函數的作用就是通過兩個參數相加并返回,所以編輯器推算出了函數返回值的類型。
對比上下兩段代碼,代碼上并沒有什么區別,也許有人會嗤之以鼻,認為代碼已經足夠清晰,并不需要額外的添加注釋來說明。
這種盲目自信一般會在接手了其他人更爛的代碼后被打破,然后再反思自己究竟做錯了什么,需要去維護這樣的代碼。
亦或者我們來放出一個稍微復雜一些的例子:
看似清晰、簡潔的一個示例,完全看不出什么毛病 _除了兩個異步await可以合并成一個_。
確實,如果這段代碼就這么一直躺在項目中,也不去改需求,那么這段代碼可以說是很完美的存在了。
如果這段代碼一直是寫下這段代碼的作者在維護,那么這段代碼在維護上也不會有什么風險。
不過如果哪天這段代碼被交接了出去,換其他的小伙伴來維護。
那么他可能會有這么幾個疑問:
getUserInfo的返回值是什么結構
createOrder的返回值又是什么結構
notify中傳入的兩個變量又都是用來做什么的
我們也只能夠從notify函數中找到一些線索,查看到前兩個函數所返回對象的部分屬性, _但是仍然不能知道這些屬性的類型是什么_。
而想要維護這樣的一段代碼,就需要占用很多腦容量去記憶,這實際上是一個性價比非常低的事情,當這段代碼再轉給第三個人時,第三個人還需要再經歷完整的流程,一個個函數、一行行代碼去閱讀,去記憶。
如果你把這個當作是對程序的深入了解程度、對業務的嫻熟掌握,那么我覺得我也幫不了你了。
就像是現在超市結賬時,沒有柜員會以能夠記憶N多商品價格而感到驕傲,掃碼槍能做到的事情,為什么要占用你的大腦呢。
如上文所說的,JSDoc 是寫在注釋中的一些特定格式內容。
在 JavaScript 文件中大部分的標記都是塊級形式的,也就是使用 /** XXX */ 來進行定義,不過如果你愿意的話,也可以寫到代碼里邊去。
JSDoc 提供了很多種標記,用于各種場景。
但并不是所有的都是常用的(而且使用了 vscode 以后,很多需要手動指定的標記,編輯器都能夠代替你完成),常用的無外乎以下幾個:
@type 標識變量類型
@param 標識函數參數類型及描述
@return 標識函數返回值類型及描述
完整的列表可以在這里找到 Block tags
基本上使用以上三種標記以后,已經能夠解決絕大部分的問題。
JSDoc 在寫法上有著特定的要求,比如說行內也必須要是這樣的結構 /** XXX */,如果是 /* XXX */ 則會被忽略。
而多行的寫法是比較常用的,在 vscode 中可以直接在函數上方鍵入 /** 然后回車,編輯器會自動填充很多的內容,包括參數類型、參數描述以及函數描述的預留位置,使用TAB鍵即可快速切換。
實際上@type的使用頻率相較于其他兩個是很低的,因為大多數情況下@type用于標識變量的類型。
而變量的來源基本上只有兩個 1. 基本類型賦值 2. 函數返回值
首先是第一個基本類型的賦值,這個基本上 vscode 就幫你做了,而不需要自己手動的去指定。
而另外一個函數的返回值,如果我們在函數上添加了@return后,那么調用該函數并獲取返回值的變量類型也會被設置為@return對應的類型。
不過因為其他兩個標記中都有類型相關的指定,所以就拿 @type 來說明一下
首先,在 JSDoc 中是支持所有的基本類型的,包括數字、字符串、布爾值之類的。
/** @type {number} */ /** @type {string} */ /** @type {boolean} */ /** @type {RegExp} */ // 或者是一個函數 /** @type {function} */ // 一個包含參數的函數 /** @type {function(number, string)} */ // Object結構的參數 /** @type {function({ arg1: number, arg2: string })} */ // 一個包涵參數和返回值的函數 /** @type {function(number, string): boolean} */
在 vscode 中鍵入以上的注釋,都可以很方便的得到動態提示。擴展復雜類型
當然了,關于函數的,還是推薦使用 @param 和 @return 來實現,效果更好一些
上邊的示例大多是基于基本類型的描述,但實際開發過程中不會說只有這么些基本類型供你使用的。
必然會存在著大量的復雜結構類型的變量、參數或返回值。
關于函數參數,在 JSDoc 中兩種方式可以描述復雜類型:
不過這個只能應用在@param中,而且復用性并不高,如果有好幾處同樣結構的定義,那我們就需要把這樣的注釋拷貝多份,顯然不是一個優雅的寫法。
又或者我們可以使用另外兩個標記,@typedef和@property,格式都與上邊提到的標記類似,可以應用在所有需要指定類型的地方:
使用@typedef定義的類型可以很輕松的復用,在需要的地方直接指定我們定義好的類型即可。
同理,這樣的自定義類型可以直接應用在@return中。
這個算是比較重要的一個標記了,用來標記函數參數的相關信息。
具體的格式是這樣的(切換到 TypeScript 后一般會移除類型的定義,改用代碼中的類型定義):
/** * @param {number} param 描述 */ function test (param) { } // 或者可以結合著 @type 來寫(雖說很少會這么寫) /** * @param param 描述 */ function test (/** @type number */ param) { }可選參數
如果我們想要表示一個參數為可選的參數,可以的在參數名上包一個[]即可。
/** * @param {number} [param] 描述 */ function test (param) { }
同事在文檔中還提到了關于默認值的寫法,實際上如果你的可選參數在參數位已經有了默認值的處理,那么就不再需要額外的添加[]來表示了,vscode 會幫助你標記。
// 文檔中提到的默認值寫法 /** * @param {number} [param=123] 描述 */ function test (param = 123) { } // 而實際上使用 vscode 以后就可以簡化為 /** * @param param 描述 */ function test (param = 123) { }
兩者效果是一樣的,并且由于我們手動指定了一個基礎類型的值,那么我們連類型的指定都可以省去了,簡單的定義一下參數的描述即可。
return該標記就是用來指定函數的返回值,用法與@param類型,并且基本上這兩個都會同時出現,與@param的區別在于,因為@return只會有一個,所以不會像前者一樣還需要指定參數名。
/** * @return {number} 描述 */ function test () { }Promise 類型的返回值處理
現在這個年代,基本上Promise已經普及開來,所以很多函數的返回值可能并不是結果,而是一個Promise。
所以在vscode中,基于Promise去使用@return,有兩種寫法可以使用:
// 函數返回 Promise 實例的情況可以這么指定類型 /** * @return {Promise小結} */ function test () { return new Promise((res) => { res(1) }) } // 或者使用 async 函數定義的情況下可以省略 @return 的聲明 async function test () { return 1 } // 如果返回值是一個其他定義了類型的函數 or 變量,那么效果一樣 async function test () { return returnVal() } /** @return {string} */ function returnVal () {}
再回到我們最初的那個代碼片段上,將其修改為添加了 JSDoc 版本的樣子:
/** * @typedef {Object} UserInfo * @property {number} uid 用戶UID * @property {string} name 昵稱 * * @typedef {Object} Order * @property {number} orderId 訂單ID * @property {number} price 訂單價格 */ async function main () { const uid = 1 const orders = await createOrder(uid) const userInfo = await getUserInfo(uid) await notify(userInfo, orders) } /** * 獲取用戶信息 * @param {number} uid 用戶UID * @return {Promise} */ async function getUserInfo (uid) { } /** * 創建訂單 * @param {number} uid 用戶UID * @return {Promise } */ async function createOrder (uid) { } /** * 發送通知 * @param {UserInfo} userInfo * @param {Order} orders */ async function notify (userInfo, orders) { }
實際上并沒有添加幾行文本,在切換到 TypeScript 之前,使用 JSDoc 能夠在一定程度上降低維護成本,尤其是使用 vscode 以后,要手動編寫的注釋實際上是沒有多少的。
但是帶來的好處就是,維護者能夠很清晰的看出函數的作用,變量的類型。代碼即文檔。
并且在進行日常開發時,結合編輯器的自動補全、動態提示功能,想必一定是能夠提高開發體驗的。
上邊介紹的只是 JSDoc 常用的幾個標記,實際上還有更多的功能沒有提到,具體的文檔地址:jsdoc
參考資料jsdoc | @return
jsdoc | @param
jsdoc | @typedef
jsdoc | @property
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103756.html
摘要:本文比較了種較為主流的注釋文檔生成工具。應該說是非常適合開源項目多個作者共同維護的一個文檔工具。最后我選擇了作為文檔生成的工具。為了支持多種語言,它僅對注釋塊內部的內容進行解析。 最近隨著寫Node以及獨立的CommonJS模塊越來越多,我發現有一份好的文檔不僅可以幫助自己在應用這些接口的時候不至于迷糊,而且對于共同開發的情況下,能夠省去大量團隊的交流和Debug的時間。 本文比較了...
摘要:優秀的代碼注釋可以提高代碼可讀性,當然優秀的命名規范也可以啦。表示函數是異步的。行注釋行注釋的話,應該不用做太多的解釋,直接用注釋相關信息就啦。 showImg(http://ws1.sinaimg.cn/large/005NRne3gy1g34cu772u0j30s00v4wko.jpg); 前言 可能現在不管大家去面試還是在公司上班都會涉及到代碼可讀性,或者是代碼規范。優秀的代碼注...
摘要:我們在對現在較主流的五個文檔工具分別作了調研和嘗試,得到結論如下工具優點缺點提供了完整的模板開發事件觸發等接口,使用非常靈活。至此,的環境部署已經全部完成了。 字數:981 閱讀時間:5分鐘 選型依據 ? 在經歷了數個上線的項目之后,筆者所在的團隊已經沉淀了一個相對穩定版本的前端框架。因此,我們需要出具一套框架API文檔,以便公司其他成員的使用和框架的后期維護。我們在對...
摘要:的出現大有統一輕量級領域之勢,在其新版本中自帶了的解析功能,幫助開發者通過書寫注釋的形式向提供必要信息,完善提示功能。如果因為這種需求就額外的,就會破壞了代碼正常的依賴關系。 弱類型腳本語言的代碼提示功能一直是開發者一個隱隱的痛點,沒有它也不是不能干活,但是經常因為出現拼寫錯誤或不經意的修改導致的變量丟失而耗費無畏的時間在與業務邏輯無關的地方。VSCode的出現大有統一輕量級IDE領域...
閱讀 3681·2021-09-22 15:28
閱讀 1300·2021-09-03 10:35
閱讀 882·2021-09-02 15:21
閱讀 3483·2019-08-30 15:53
閱讀 3500·2019-08-29 17:25
閱讀 575·2019-08-29 13:22
閱讀 1560·2019-08-28 18:15
閱讀 2290·2019-08-26 13:57