正如咱們在 代碼結構 一文所瞭解到的那樣,註釋能夠是以 //
開始的單行註釋,也能夠是 /* ... */
結構的多行註釋。javascript
咱們一般經過註釋來描述代碼怎樣工做和爲何這樣工做。html
乍一看,寫註釋可能很簡單,但初學者在編程的時候,常常錯誤地使用註釋。java
新手傾向於使用註釋來解釋「代碼中發生了什麼」。就像這樣:react
// 這裏的代碼會先作這件事(……)而後作那件事(……)
// ……誰知道還有什麼……
very;
complex;
code;
複製代碼
但在好的代碼中,這種「解釋性」註釋的數量應該是最少的。嚴格地說,就算沒有它們,代碼也應該很容易理解。git
關於這一點有一個很棒的原則:「若是代碼不夠清晰以致於須要一個註釋,那麼或許它應該被重寫。」github
有時候,用一個函數來代替一個代碼片斷是更好的,就像這樣:web
function showPrimes(n) {
nextPrime:
for (let i = 2; i < n; i++) {
// 檢測 i 是不是一個質數(素數)
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert(i);
}
}
複製代碼
更好的變體,使用一個分解出來的函數 isPrime
:算法
function showPrimes(n) {
for (let i = 2; i < n; i++) {
if (!isPrime(i)) continue;
alert(i);
}
}
function isPrime(n) {
for (let i = 2; i < n; i++) {
if (n % i == 0) return false;
}
return true;
}
複製代碼
如今咱們能夠很容易地理解代碼了。函數本身就變成了一個註釋。這種代碼被稱爲 自描述型 代碼。編程
若是咱們有一個像下面這樣很長的代碼塊:微信
// 在這裏咱們添加威士忌(譯註:國外的一種酒)
for(let i = 0; i < 10; i++) {
let drop = getWhiskey();
smell(drop);
add(drop, glass);
}
// 在這裏咱們添加果汁
for(let t = 0; t < 3; t++) {
let tomato = getTomato();
examine(tomato);
let juice = press(tomato);
add(juice, glass);
}
// ...
複製代碼
咱們像下面這樣,將上面的代碼重構爲函數,可能會是一個更好的變體:
addWhiskey(glass);
addJuice(glass);
function addWhiskey(container) {
for(let i = 0; i < 10; i++) {
let drop = getWhiskey();
//...
}
}
function addJuice(container) {
for(let t = 0; t < 3; t++) {
let tomato = getTomato();
//...
}
}
複製代碼
一樣,函數自己就能夠告訴咱們發生了什麼。沒有什麼地方須要註釋。而且分割以後代碼的結構也更好了。每個函數作什麼、須要什麼和返回什麼都很是地清晰。
實際上,咱們不能徹底避免「解釋型」註釋。例如在一些複雜的算法中,會有一些出於優化的目的而作的一些巧妙的「調整」。可是一般狀況下,咱們應該儘量地保持代碼的簡單和「自我描述」性。
因此,解釋性註釋一般來講都是很差的。那麼哪種註釋纔是好的呢?
描述架構 : 對組件進行高層次的總體歸納,它們如何相互做用、各類狀況下的控制流程是什麼樣的……簡而言之 —— 代碼的鳥瞰圖。有一個專門用於構建代碼的高層次架構圖,以對代碼進行解釋的特殊編程語言 UML。絕對值得學習。
記錄函數的參數和用法:有一個專門用於記錄函數的語法 JSDoc:用法、參數和返回值。
例如:
/** * 返回 x 的 n 次冪的值。 * * @param {number} x 要改變的值。 * @param {number} n 冪數,必須是一個天然數。 * @return {number} x 的 n 次冪的值。 */
function pow(x, n) {
...
}
複製代碼
這種註釋能夠幫助咱們理解函數的目的,而且不須要研究其內部的實現代碼,就能夠直接正確地使用它。
順便說一句,不少諸如 WebStorm 這樣的編輯器,均可以很好地理解和使用這些註釋,來提供自動補全和一些自動化代碼檢查工做。
固然,也有一些像 JSDoc 3 這樣的工具,能夠經過註釋直接生成 HTML 文檔。你能夠在 usejsdoc.org/ 閱讀更多關於 JSDoc 的信息。
爲何任務以這種方式解決:寫了什麼代碼很重要。可是爲何 不 那樣寫可能對於理解正在發生什麼更重要。爲何任務是經過這種方式解決的?代碼並無給出答案。
若是有不少種方法均可以解決這個問題,爲何恰恰是這一種?尤爲當它不是最顯而易見的那一種的時候。
沒有這樣的註釋的話,就可能會發生下面的狀況:
解決方案的註釋很是的重要。它們能夠幫助你以正確的方式繼續開發。
代碼有哪些巧妙的特性?它們被用在了什麼地方:若是代碼存在任何巧妙和不顯而易見的方法,那絕對須要註釋。
一個好的開發者的標誌之一就是他的註釋:它們的存在甚至它們的缺席(譯註:在該註釋的地方註釋,在不須要註釋的地方則不註釋,甚至寫得好的自描述函數自己就是一種註釋)。
好的註釋可使咱們更好地維護代碼,一段時間以後依然能夠更高效地回到代碼高效開發。
註釋這些內容:
避免註釋:
註釋也被用於一些如 JSDoc3 等文檔自動生成工具:他們讀取註釋而後生成 HTML 文檔(或者其餘格式的文檔)。
本文首發於微信公衆號「技術漫談」,歡迎微信搜索關注,訂閱更多精彩內容。
現代 JavaScript 教程:開源的現代 JavaScript 從入門到進階的優質教程。React 官方文檔推薦,與 MDN 並列的 JavaScript 學習教程。
在線免費閱讀:zh.javascript.info
掃描下方二維碼,關注微信公衆號「技術漫談」,訂閱更多精彩內容。