編寫可維護的JavaScript
每次亞馬遜或者京東滿xxx打折的時候,總會湊單擼各種奇怪的不知道哪年才會翻開來看看的書(大家不是都這樣么:) )。前兩天給同事 code review JavaScript 代碼,由于我經驗不豐富,看著總覺得心里沒底。轉眼瞥見書架上夾著一本 《編寫可維護的 JavaScript》 ,雖然怎么想也想不起是什么時候買回來的,但記得 Sneezry 老師推薦過本書,便立馬拿出來翻了翻。
作者 Nicholas C.Zakas 曾是 Yahoo! 的首席前端開發工程師(現在跑到 Box 去了),在書中介紹了編程風格、編程實踐和自動化方面的 best practice 。大師果然就是大師啊,短短數小時內,我便產生了深深的共鳴,腦洞也各種大開。內心的喜悅不能獨享,我決定為它寫篇博文,講一講其中的“高光時刻”。
編程風格
本書的第一部分講解如何使用統一的編程風格,降低團隊項目的維護成本。幾乎每一門語言都有自己的 styling rule ,靠譜的技術企業甚至會在企業內部推行的自己的編程風格(比如在 baidu 寫 C++ )。
當我們談論風格時,我們其實是在說
- 縮進
- 換行
- 行的長度
- 花括號的對齊
- 注釋
- 命名
- etc
你幾乎可以在每一本語言書上找到這些章節。書中推薦使用 JSHint JSLint 等編程風格檢查工具,個人覺得,選擇其中一種并且推行下去既可以了,事半功倍。
編程實踐
這一部分就是講編程過程中的 best practice
UI層的松耦合
我們知道在Web開發中,用戶界面由 HTML, CSS 和 JavaScript 三層一起構建的
- HTML 定義頁面數據和語義
- CSS 給頁面添加樣式,創建視覺特征
- JavaScript 用來給頁面添加行為
我們應當努力減少這三層之間的依賴性,讓更改單獨修改某個組件時無需修改其他組建。作者給出的建議,有這幾條我覺得值得牢記
- 將 CSS 從 JavaScript 中抽離。舉一個實際的栗子,我們經常在頁面上實現 lazy loading,在 request 發送出去之后,我們會秀出一張菊花圖提示用戶正在加載,加載完畢后,隱藏或者刪除掉這個張菊花圖。最直接的做法就是在 ajax call 前后調整這張圖片的 display 屬性。但是這么做會帶來一個問題,樣式是由 JavaScript 而非 CSS 來加載的,當出現樣式的問題時,我們會第一時間查看 CSS,但?最直 當我們查到精盡人亡的時候,我們才發現樣式是由 JavaScript 改變的,一定會哭的。Best practise 是把所有樣式保留在 CSS 中,當需要用 JavaScript 來修改元素樣式時, 操作 CSS 的 className (計算元素定位例外)。
- 將 JavaScript 從 HTML 中抽離。很多初學者都會把腳本嵌入到 HTML 中來運行,比如在 element 上綁定 onclick 屬性或者使用<script>標簽。在這種情況下,當你需要更新這個方法的命名,你總需要更新 HTML 頁面;內嵌的 JavaScript 會給調試和 troubleshoot 帶來難度(至少是增加了復雜度)。Best practise 是 把絕大多數的** JavaScript 代碼放在外部文件中**。
- 將 HTML 從 JavaScript 中抽離。模版化發展到今天,這條規律幾乎不言自明了。
避免空比較
這個比較繞口,舉個例子大家就明白了,通暢我們設計一個函數時,需要考慮傳進來的參數是否正確,比如不能為空,不能為 undefined 。像下面這段代碼:
function Process(items) { if (items !== null) { items.sort(); items.forEach(function (item) {}); } }
事實上在這段代碼中,我們真正關心的是 items 這個 object 是否為一個 Array 。單純的和 null 進行比較,代碼的可讀性不好,coverage 也不夠。本書的建議是,使用諸如 typeof, instance of 等來檢測原始值( primitive value)、引用值和函數等。
if (typeof name === "string") { }
上面的代碼就清晰的交代了函數期待 name 這個 variable 是一個 string 而非其他類型的值。
其他
這一部分其他章節,個人覺得在其他編程語言中也基本適用,比如
- 避免使用全局變量
- 使用命名空間和模塊
- 將配置數據從代碼中分離出來
- 自定義 error
或者比較 hacky,比如 瀏覽器嗅探。讀者可以在互聯網上找到更全面的解決方案。
自動化
第三部分,作者花了八個章節來講解如何對前端代碼進行開發、測試、部署、文檔的自動化。作者寫這本書的時間距離現在已經過去數年,前端自動化已經逐漸成熟并且被廣泛接受,你一定或多或少見到過以下工具
- Task Runner. Grunt/Gulp,這兩個工具其實代表的是一套工具鏈,比如代碼合并(concat),代碼壓縮(minification),代碼風格審查( JSHint/Lint)等等,然后通過 task runner 將這些工具組合到一起。
- CI. Jenkins/TeamCity
- Test Framework. Protractor/Selenium
- etc…
如果你們的前端團隊還沒有使用到上面提到的任何工具(或者自己造了類似的輪子),那情況可能就有點不妙了。
放在最后
不管我自己是否承認,我已經成為了一個半路出家的前端工程師了,和我最先估計的職業生涯路線有點偏差。我司大部分部門招人的策略是招聰明的人而非招專業的人,這就導致了來我司前你耍什么技術已經不那么重要。過去我司比較保守,一定要 dogfood,大家來了就只能使用 .NET,使用開源或者別家的技術十分謹慎。但是這兩年突然 open 起來了,按照需求你可以自由地選擇前端框架(像我們就用 Angular)、緩存(Redis已經稱為第一選擇,大阿哥AppFabric被廢黜了)、搜索引擎(elastic search 大家都得用啊)、測試框架(Selenium已經接連KO VS測試框架和MTM)等等等等,不知不覺中人人都變成了全棧工程師。也不知道這算不算好事。
簡言之,讀者朋友們不太可能在我的博客上看到 .NET 的文章了,讓你們失望啦 :)