天天看點

如何寫出優雅的 JS 代碼,變量和函數的正确寫法

在開發中,變量名,函數名一般要做到清晰明了,盡量做到看名字就能讓人知道你的意圖,是以變量和函數命名是挺重要,今天來看看如果較優雅的方式給變量和函數命名。

我們讀的會比我們寫的多得多,是以如果命名太過随意不僅會給後續的維護帶來困難,也會傷害了讀我們代碼的開發者。讓你的變量名可被讀取,像 buddy.js 和 ESLint 這樣的工具可以幫助識别未命名的常量。

顯式用于隐式

如果類名/對象名已經說明了,就無需在變量名中重複。

限制函數參數的數量是非常重要的,因為它使測試函數變得更容易。如果有三個以上的參數,就會導緻組合爆炸,必須用每個單獨的參數測試大量不同的情況。

一個或兩個參數是理想的情況,如果可能,應避免三個參數。 除此之外,還應該合并。大多數情況下,大于三個參數可以用對象來代替。

這是目前為止軟體工程中最重要的規則。當函數做不止一件事時,它們就更難組合、測試和推理。可以将一個函數隔離為一個操作時,就可以很容易地重構它,代碼也會讀起來更清晰。

當有一個以上的抽象層次函數,意味該函數做得太多了,需要将函數拆分可以實作可重用性和更簡單的測試。

盡量避免重複的代碼,重複的代碼是不好的,它意味着如果我們需要更改某些邏輯,要改很多地方。

通常,有重複的代碼,是因為有兩個或多個稍有不同的事物,它們有很多共同點,但是它們之間的差異迫使我們編寫兩個或多個獨立的函數來完成許多相同的事情。 删除重複的代碼意味着建立一個僅用一個函數/子產品/類就可以處理這組不同僚物的抽象。

獲得正确的抽象是至關重要的,這就是為什麼我們應該遵循類部分中列出的 SOLID原則。糟糕的抽象可能比重複的代碼更糟糕,是以要小心!說了這麼多,如果你能做一個好的抽象,那就去做吧!不要重複你自己,否則你會發現自己在任何時候想要改變一件事的時候都要更新多個地方。

設計模式的六大原則有:

Single Responsibility Principle:單一職責原則

Open Closed Principle:開閉原則

Liskov Substitution Principle:裡氏替換原則

Law of Demeter:迪米特法則

Interface Segregation Principle:接口隔離原則

Dependence Inversion Principle:依賴倒置原則

把這六個原則的首字母聯合起來(兩個 L 算做一個)就是 SOLID (solid,穩定的),其代表的含義就是這六個原則結合使用的好處:建立穩定、靈活、健壯的設計。下面我們來分别看一下這六大設計原則。

不好的寫法

好的寫法

标志告訴使用者,此函數可以完成多項任務,函數應該做一件事。 如果函數遵循基于布爾的不同代碼路徑,請拆分它們。

如果函數除了接受一個值并傳回另一個值或多個值以外,不執行任何其他操作,都會産生副作用。 副作用可能是寫入檔案,修改某些全局變量,或者不小心将你的所有資金都彙給了陌生人。

在JavaScript中,原始類型值是按值傳遞,而對象/數組按引用傳遞。 對于對象和數組,如果有函數在購物車數組中進行了更改(例如,通過添加要購買的商品),則使用該購物車數組的任何其他函數都将受到此添加的影響。 那可能很棒,但是也可能不好。 來想象一個糟糕的情況:

使用者單擊“購買”按鈕,該按鈕調用一個purchase 函數,接着,該函數發出一個網絡請求并将cart數組發送到伺服器。由于網絡連接配接不好,purchase函數必須不斷重試請求。現在,如果在網絡請求開始之前,使用者不小心點選了他們實際上不需要的項目上的“添加到購物車”按鈕,該怎麼辦?如果發生這種情況,并且網絡請求開始,那麼購買函數将發送意外添加的商品,因為它有一個對購物車數組的引用,addItemToCart函數通過添加修改了這個購物車數組。

一個很好的解決方案是addItemToCart總是克隆cart數組,編輯它,然後傳回克隆。這可以確定購物車引用的其他函數不會受到任何更改的影響。

關于這種方法有兩點需要注意:

1.可能在某些情況下,我們确實需要修改輸入對象,但是當我們采用這種程式設計實踐時,會發現這種情況非常少見,大多數東西都可以被改造成沒有副作用。

2.就性能而言,克隆大對象可能會非常昂貴。 幸運的是,在實踐中這并不是一個大問題,因為有很多很棒的庫使這種程式設計方法能夠快速進行,并且不像手動克隆對象和數組那樣占用大量記憶體。

污染全局變量在 JS 中是一種不好的做法,因為可能會與另一個庫發生沖突,并且在他們的生産中遇到異常之前,API 的使用者将毫無用處。 讓我們考慮一個示例:如果想擴充 JS 的原生Array方法以具有可以顯示兩個數組之間差異的diff方法,該怎麼辦? 可以将新函數寫入Array.prototype,但它可能與另一個嘗試執行相同操作的庫發生沖突。 如果其他庫僅使用diff來查找數組的第一個元素和最後一個元素之間的差別怎麼辦? 這就是為什麼隻使用 ES6 類并簡單地擴充Array全局會更好的原因。

JavaScript不像Haskell那樣是一種函數式語言,但它具有函數式的風格。函數式語言可以更簡潔、更容易測試。如果可以的話,盡量喜歡這種程式設計風格。

這似乎是一個不可能完成的任務。一聽到這個,大多數人會說,“沒有if語句,我怎麼能做任何事情呢?”答案是,你可以在許多情況下使用多态性來實作相同的任務。

第二個問題通常是,“那很好,但是我為什麼要那樣做呢?”答案是上面講過一個概念:一個函數應該隻做一件事。當具有if語句的類和函數時,這是在告訴你的使用者該函數執行不止一件事情。

JavaScript 是無類型的,這意味着函數可以接受任何類型的參數。 有時q我們會被這種自由所困擾,并且很想在函數中進行類型檢查。 有很多方法可以避免這樣做。 首先要考慮的是一緻的API。

現代浏覽器在運作時做了大量的優化工作。很多時候,如果你在優化,那麼你隻是在浪費時間。有很好的資源可以檢視哪裡缺乏優化,我們隻需要針對需要優化的地方就行了。