https://juejin.im/post/5e31cf0be51d4502051967ae編程
原文發佈與個人博客 lambdas.dev。api
摸魚時更新。數組
好的代碼不只是在性能、體積、內存,更要 code for humans
。緩存
咱們知道代碼被人閱讀的難度遠勝於引擎,要寫出好的代碼須要脫離本身的視角,以他人的眼光審視,從新理解上下文含義, 此時代碼的架構、拆分、組合、技巧則給予人閱讀的幸福感,咱們致力於構建優秀的代碼意味着不只以代碼爲工具,更是將其視做傳達智慧、 思想、理念的橋樑。這是一種智慧上的錘鍊與分享。性能優化
1. 優先使用 const
。
const
在 JavaScript 中不只能夠用於命名常量,由於其用於保證內存地址不可變,因此也經常使用於聲明對象與數組。在編程中多使用 const
代替 let
, 能夠在風格上向 immutable
靠攏,在編程思惟上開始擯棄反作用。更多的使用 const
雖然可能使聲明項增多,但對於開發者來講,更少的心智負擔和語義化 命名會使代碼質量大大上升。架構
在 JS 中若是過多的使用 let
聲明變量,閱讀者每每須要貫穿上下文反覆閱讀才能理解當前變量的值,且變量可能被其餘函數引用更改,顯而易見, 使用變量越多理解的成本也就越高,並且你很難追蹤變量具體的值。以下方代碼統計數組每一個值的總和。使用 const
命名一個常量後, 你將沒法使用 forEach
在每一次循環時改動它,轉而使用 reduce
,咱們減小了變量 count
,增長了常量 count
,在隨後代碼的引用中就無需擔心 變量的狀態,由於咱們知道,count
只能是一個數值,而不會變化。函數
// bad let count = 0 [...].forEach(item => { count += item }) // good const count = [...].reduce((pre, current) => pre + current, 0) 複製代碼
2. 使用函數表達式優於函數聲明
配合上文所提到的 const
,咱們可以使用函數表達式來建立一個函數,更多的時候咱們會與箭頭函數配合食用 const f = () => {}
。它們優於傳統函數聲明的地方在於:工具
- 語義化的指明函數是不可變的。
- 函數表達式能夠被看作賦值語句,更加簡單易懂,且沒法被覆蓋。(常量不能夠被重複聲明)
- 函數聲明會在解析時被提高,存在先使用後聲明。高可讀的代碼應當先聲明再調用,使用表達式範式能夠約束這一點。
- 搭配箭頭函數使用可減輕對
this
的思惟依賴。
// bad function addOne(value) { return value + 1 } // good const addOne = value => value + 1 複製代碼
3. 使用 return 減小縮進
縮進問題在 JS 代碼中更廣泛,推薦在可能的代碼塊中使用 return
優先返回,如 function
if else
等語句。這樣能夠有效的減小縮進,同時也能使 代碼更加的清晰可讀,由於在同一時間內老是隻作一件事。post
咱們還能夠在必要時優先 return
較短的語句,使代碼更美觀。性能
// bad const render = () => { if (isServer) { // server code } else { // client code } } // good const render = () => { if (isServer) return // server code // client code } 複製代碼
4. 不要過分優化
若是你不是編寫類庫、底層代碼等對性能要求極爲苛刻時,請勿過分優化性能。絕大多數沒必要要的性能優化會使代碼可讀性急劇降低。這很是重要。
例 1,沒必要要的減小內存空間
// bad let fullname users.forEach(user => { fullname = user.firstname + user.lastname // ... register(fullname) }) // good users.forEach(user => { const fullname = user.firstname + user.lastname // ... register(fullname) }) 複製代碼
例 2,沒必要要的運算優化
// bad let len = users.length for (i = 0; i < len; i ++) {} // good users.forEach(user => {}) 複製代碼
5. 減小魔術字符
魔術字符 (魔術數字) 指的是代碼中出現意義不明的字符,從上下文沒法推論其來源與做用,這會使代碼難以擴展。
一般,咱們還會把全部的字符或數字統一聲明在一個常量文件內,如 host
defaultSettings
port
等等,這會有益於維護。
// bad const url = `${host}/2/users` // good const apiVersion = 2 const apis = { users: 'users', projects: 'projects', // ... } const url = `${host}/${apiVersion}/${apis.users}` 複製代碼
6. 函數不要有過多參數
在不斷延展的需求中,咱們的函數會有愈來愈多的參數,但要注意,當一個函數的參數較多時會使調用方困擾。咱們並不是須要全部的函數都實現 curry
,但減小 函數參數、合併參數、分離函數都會顯著提高代碼的可讀性與擴展性。
在調用較多參數的函數時,咱們不只要緊記每一個參數的順序,還要對空缺的參數進行補位 (如傳入 null
undefined
等),這會致使聲明與調用的代碼中都被迫 存在很是多的變量與判斷。在函數個數增加時能夠考慮將其中的一部分合成爲一個對象參數,或是將一部分功能拆離,做爲一個新的函數。
// bad const createUser = (id, name, createdAt, telephone, email, address) => {} // good const createUser = (id, userOptions) => {} 複製代碼
7. 保持函數的專一
在一個函數中組好只作一件事,同時也最好保證這件事是與函數的名稱是相關的。在單個函數中累積邏輯會給閱讀者帶來很是大的心智負擔,若是咱們予以函數拆分、 合理化的命名、組合,就能使代碼總體得到極大的美感,看起來層次分明,涇渭分明。
// bad const getUser = id => { const headers = // ... const options = // ... options.headers = headers const host = // ... const url = // ... if (id.length > 1) // ... return fetch(url, options) } // good const makeOptions = () => {} const makeUrl = id => {} const getuser = id => { const options = makeOptions() const url = makeUrl(id) return fetch(url, options) } 複製代碼
8. 使用語義化命名代替長條件
過長的條件判斷經常會在一段時間後變的匪夷所思,很難理解其中的邏輯,將其使用語義化的常量代替則可向閱讀者提示意義,更省略了沒必要要的註釋。
// bad // the code for teen-ager if (user.age < 19 && user.age > 13) { // ... } // good const isTeenAgerMember = user.age < 19 && user.age > 13 if (isTeenAgerMember) // ... 複製代碼
9. 減小函數的反作用
減小函數的反作用並不是老是須要以純函數來解決全部問題,沒必要慌張,咱們知道反作用會使狀態的變化難以琢磨,在編程中應當以較少的反作用函數爲目標, 使函數的預期與實際保持一致的同時不至於形成過多的影響,這或許會使在構思和聲明時花費一些時間,但對上下文的代碼塊來講,是一件好事。
你可能發現有些時候會不可避免的改變了某些外部狀態,好比緩存某些值,爲此你陷入了重構的苦思,事實是沒必要過於擔心,你想作的就必然有道理。這就是 編程中的取捨 。學會在編程、架構、工程上有所取捨 (不是爲所欲爲) 後構建出的產品天然會嵌上獨具一格的風采,這就是你的編程。
// bad let user = getUser() const upload = () => { user.name = `${user.name}-upload` // fetch user ... } // good const user = getUser() const upload = user => { const body = Object.assign({}, user, { name: `${user.name}-upload` }) // fetch body ... } upload(user) 複製代碼