JS 優雅指南.1

https://juejin.im/post/5e31cf0be51d4502051967ae編程


原文發佈與個人博客 lambdas.devapi

摸魚時更新。數組


好的代碼不只是在性能、體積、內存,更要 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)
複製代碼

連接

相關文章
相關標籤/搜索