JavaScript[2] 一直處于近年來最常用的腳本語言之一的地位。它以在 Web 平臺上編寫腳本的便捷性而聞名。隨著語言本身的發展,它從最開始蹭 Java 熱度的“玩具”語言,變成了一種成熟的語言,還能用來構建大的應用了。
不幸的是,隨著深入使用,JavaScript 語言本身的缺陷也被保留出來,包括:
2014 年,微軟推出了 Typescript v1.0[3]。這改變了整個 JavaScript 生態系統。
TypeScript[4] 是 JavaScript 語言的超集,它解決了上一節提到的問題以及更多其他問題。這使得它越來越受歡迎。
State of Js survey 2022[5] 展示的 TypeScript 使用率在上升。
圖片
TypeScript 雖然解決了很多問題,但也有缺點。
本文我們將研究 TypeScript 的一個非常好的替代方案——JSDoc,它解決了靜態類型和可擴展問題,同時還消除了 JavaScript 生態系統中 TypeScript 的缺點。
JSDoc[6] 是基于 JavaScript 語言注釋功能建立起的一套文檔系統。可以幫助你在編寫 JavaScript 代碼的同時,通過使用包含 JSDoc 語法的注釋獲得文檔支持。
JSDoc 語法有多種用途,包括為變量聲明類型、指定函數參數和返回值的類型、記錄和提供函數的使用方式、避免拼寫錯誤等。這些特性與 TypeScript 類似,可以被像 VS Code 這類現代代碼編輯器利用,為程序員提供構建、使用或維護代碼的支持。
JSDoc 和 TypeScript 都解決了編寫和維護純 JavaScript 代碼的問題。然而,他們使用了不同的策略,各有優缺點。
JSDoc 相對于 Typescript 的優點:
雖然 JSDoc 比 TypeScript 有很多優勢。但現狀是 Typescript 使用率不斷攀升,被大家越來越多地采用,這是有原因的。以下是 Typescript 相對于 JSDoc 的一些優點:
JSDoc 存在很久了,因此所有現代編輯器中都廣泛支持它,開箱即用,無需任何安裝。
在 .js 文件中添加 JSDoc 至此,就是增加注釋,是通過添加帶有額外星號(*)的注釋來完成的。
// Normal Javascript Comment 1/* Normal Javascript Comment 2 */ /** JSDoc 需要使用 2 個星號 */
接下來,我們介紹一些基本功能。
/** JSDoc 用來服務的語言 */const language = "JavaScript"
/** * 本篇文章的作者 * @type {string} */const writerName = "Elijah"
以上注解表示變量 writerName 是字符串類型。
/** * @type {Array<string>} */const colours = ['red', 'blue', 'green']/** * @type {Array<number[]>} */const primeNumbers = [1, 2, 3, 5, 7]
以上 2 種方法都是有效的 JSDoc 注解(與 TypeScript 一樣)。
而對象類型則可以通過 @typedef 指令來創建。
/** * @typeof {Object} User - A user schema * @property {number} id * @property {string} username * @property {string} email * @property {Array<number>} postLikes * @property {string[]} friends */
/** @type {User} */const person1 = { id: 847, username: "Elijah", email: "elijah@user.com", postLikes: [44, 22, 24, 39], friends: ['fede', 'Elijah']}
/** @type {User} */const person2 = { id: 424, username: "Winston", email: "winston@user.com", postLike: [18, 53, 98], friends: ['Favour', 'Jane']}
/** * Divide two numbers. * @param {number} dividend - The number to be divided. * @param {number} divisor - The number to divide by. * @returns {number} The result of the division. */function divideNumbers(dividend, divisor) { return dividend/divisor;}
@param關鍵字后面跟參數類型定義,還可以使用連字符 - 添加參數描述。
@returns 關鍵字用于定義函數返回類型。這對于大型函數特別有用,因為這類函數一般很難觀察它預期的返回類型。
此外,你可以使用 @throws 指令添加函數可能的拋錯類型。
接下來,改進 divideNumbers 函數,增加除數為零時的拋錯支持。
/** * Divide two numbers. * @param {number} dividend - The number to be divided. * @param {number} divisor - The number to divide by. * @returns {number} The result of the division. * @throws {ZeroDivisionError} Argument divisor must be non-zero */function divideNumbers(dividend, divisor) { if (divisor === 0) { throw new DivisionByZeroError('Cannot Divide by zero') } return dividend/divisor;}
你可以在 @throws 中同時指定錯誤類型以及錯誤描述。
/** * Custom error for division by zero. */class DivisionByZeroError extends Error { constructor(message = "Cannot Divide By Zero") { super(message); this.name = "DivisionByZeroError"; }}
由于 JavaScript 本身并不強制你處理錯誤,因此這樣做一定程度上有助于改善代碼協作、便于維護。
更進一步,你還可以使用 JSDoc 為 class 提供類型支持。
/** * A Rectangle Class * @class * @classdec A four-sided polygon with opposite sides of equal length and four right angles */class Rectangle { /** * Initializing a Rectangle object. * @param {number} length - The length of the rectangle. * @param {number} width - The width of the rectangle. */ constructor(length, width) { this.length = length; this.width = width; } /** * Calculate the area of the Rectangle * @returns {number} The area of the rectangle. */ calculateArea() { return this.length * this.width; } /** * Calculate the perimeter of the rectangle. * @returns {number} The perimeter of the rectangle. */ calculatePerimeter() { return 2 * (this.length + this.width); }}
上面是一個簡單的矩形類,提供了 2 種方法分別用來計算其面積和周長。
@class 關鍵字用于表示這個函數需要使用 new 關鍵字調用,@classdec 用于類的描述。為類添加類型時,重要的是進一步添加類型和描述。
我們使用 @params 關鍵字來提供需要傳遞到構造函數中的參數的類型和描述。類中的方法的類型化方式與函數相同,這在上一節中已介紹過,就不再贅述。
除了向代碼添加基本類型之外,JSDoc 還有很多方法可以幫助提高可讀性性。這里有幾個:
/** * Possible title for this article * @type {string} * @author Elijah [elijah@example.com] */const articleTitle = "Demystifying JSDoc"
/** * Sums of the square of two numbers a**2 + b**2 * @example <caption>How to use the sumSquares function</caption> * // returns 13 * sumSquares(2, 3) * @example * // returns 41 * sumSquares(4, 5) * // Typing the function * @param {number} a - The first number * @param {number} b - The second number * @returns {Number} Returns the sum of the squares */const sumSquares = function(a, b){ return a**2 + b**2}
我們使用 @example 指令來實現這一點,也可以使用 <caption> 標簽作為標題。
/** * @version 1.0.0 * @type {number} */const meaningOfLife = 42
/** * How to use the link tags * Also see the {@link https://jsdoc.app/tags-inline-link.html official docs} for more information * @tutorial getting-started */function myFunction (){}
@link 指令將“official docs”渲染成指向某個地址的文字鏈接。而 @tutorial 指令則用于將用戶引導至生成文檔上的相關教程鏈接。
// jsdoc.js/** @module firstDoc *///The rest of the code goes here
使用 JSDoc 的最大優點之一是能夠將 JSDoc 文件轉換為生成文檔網站——甚至是 Typescript,這樣他們就可以獲得使用 Typescript 的好處。
如上所述,你可以按照以下步驟生成更具可讀性的 GUI:
$ npm install -g jsdoc
$ jsdoc path/to/file.js
這是默認 jsdoc 生成的模板的樣子,但你可以設置成不同的模板配置[7]。
TypeScript 中的 .d.ts 文件表示聲明文件,你可以使用以下步驟從 JSDoc 代碼生成這些文件:
$ npm install tsd-jsdoc
對于單個文件。
$jsdoc -t node_modules/tsd-jsdoc/dist -r our/jsdoc/file/path.js
對于多個文件。
$jsdoc -t node_modules/tsd-jsdoc/dist -r file1.js file2.js file3.js ...
對于整個文件夾。
$jsdoc -t node_modules/tsd-jsdoc/dist -r src
它會將文件中的所有類型合并到 單個文件 out/types.d.ts 中。
注意:這假設你已經安裝了上一節中的 jsdoc 。如果沒有,請在運行此步驟之前先安裝它。
至此,我們已經學習了使用 JSDoc 以及從 JSDoc 代碼生成類型和文檔網站的基礎知識。當 Typescript 編譯/構建步驟對生產力產生負面影響時,JSDoc 特別有用。對遺留代碼庫來說 JSDoc 也很有用。
Rich Harris(Svelte 和 SvelteKit 的創建者)也將整個 Svelte 和 SvelteKit 倉庫從 TypeScript 改用 JSDoc[8]。另外,TypeScript 也添加了對許多 JSDoc 聲明的支持(來源[9])。
參考資料
[1]JSDoc: A Solid Alternative To TypeScript: https://blog.openreplay.com/jsdoc--a-solid-alternative-to-typescript
[2]JavaScript: https://en.wikipedia.org/wiki/JavaScript
[3]Typescript v1.0: https://devblogs.microsoft.com/typescript/announcing-typescript-1-0/
[4]TypeScript: https://www.typescriptlang.org/
[5]State of Js survey 2022: https://2022.stateofjs.com/en-US/usage/
[6]JSDoc: https://jsdoc.app/
[7]模板配置: https://jsdoc.app/about-configuring-default-template.html
[8]從 TypeScript 改用 JSDoc: https://github.com/sveltejs/kit/discussions/4429
[9]來源: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
本文鏈接:http://www.www897cc.com/showinfo-26-80832-0.htmlJSDoc:一個可選的 TypeScript 替代品
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 面試官:聽說你很懂線程池?