JS程式碼簡潔之道--函式
阿新 • • 發佈:2020-06-30
函式的引數越少越好
有一個準則是:如果你的函式引數超過兩個,就應該改為物件傳入。
這樣做是合理的,因為當函式引數超過兩個時,引數順序開始變得難以記憶,而且容易出現一種很尷尬的情況:比如我只需要傳入第三個引數,因為其自身順序的原因,不得不補齊前兩個根本用不上的引數,以讓它順利排在第三位。
// bad const createArticle = (title, author, date, content) => { } createArticle('震驚,一男子竟偷偷幹這事', 'zhangnan', '2020/06/29', '某天深夜,我喝多了點酒...') // good const createArticle = ({title, author, date, content}) => { } createArticle({ title: '震驚,一男子竟偷偷幹這事', author: 'zhangnan', date: '2020/06/29', content: '某天深夜,我喝多了點酒...' })
保持函式的單一職責原則
這是軟體開發領域亙古不變的一個真理,讓一個函式只專注於一件事情,能夠很好的解耦各個功能之間的聯絡,使得後續對某一個功能進行更改時,不用擔心會影響其他模組。
假設我們現在有一個需求:現在需要給班裡的每一個同學發放假簡訊通知,如果是男生,就用電信主機號來發,如果是女生,則用聯通主機號發,同時額外發送一封愛心郵件。實現如下:
// bad 程式碼擠成一堆,很難理清 // 男生女生的通知方式還有所不同,後期如果要改動女生的通知方式,很難保證不會影響到男生 // 因為大家都寫在同一個函式裡 const notifyStudents = (studentList) => { studentList.forEach(student => { if (student.gender === 'male') { const sender1 = new SmsSender({ carrier: '電信' }); sender1.init(); sender1.sendTo(student) } else { const sender2 = new SmsSender({ carrier: '聯通' }); sender2.init(); sender2.sendTo(student); const sender3 = new EmailSender({ type: 'QQ郵箱' }); sender3.connect(); sender3.sendTo(student) } }) } // good 函式拆分,各司其職,清晰明瞭 // 雖然看起來程式碼量多了一點點 // 但是分工明確,互不影響 const initSmsSender = (carrier) => { const sender = new SmsSender({ carrier }); sender.init(); } const initEmailSender = (type) => { const sender = new EmailSender({ type }); sender.connect(); } const notifyMales = (studentList) => { const smsSender = initSmsSender('電信'); const maleList = studentList.filter(student => student.gender === 'male'); maleList.forEach(male => smsSender.sendTo(male)); } const notifyFemales = (studentList) => { const smsSender = initSmsSender('聯通'); const emailSender = initEmailSender('QQ郵箱'); const femaleList = studentList.filter(student => student.gender === 'female'); femaleList.forEach(female => { smsSender.sendTo(female); emailSender.sendTo(female); }) }
封裝條件語句
像有一些條件語句,可能存在很多與或非邏輯,如果直接寫在函式裡面,每次都需要重新理一遍,費時費力。把一堆條件語句封裝在一個函式裡面,不僅遵循單一職責原則,也將使得閱讀更加方便。
// bad const shouldIBuyThisPhone = (phone) => { const {price, year, brand} = phone; if (price > 5000 && year === new Date.getFullYear() && brand === 'huawei') { // 馬上剁手 } } // good const isHuaweiFlagShipThisYear = ({ price, year, brand }) => { const HIGH_PRICE = 5000; return price > HIGH_PRICE && year === new Date.getFullYear() && brand === 'huawei' } const shouldIBuyThisPhone = (phone) => { if (isHuaweiFlagShipThisYear(phone)) { // 馬上剁手 } }
高層函式不要依賴具體實現
在一些動作函式中,常見的一種情況是傳一個flag引數,通過對標誌變數的判斷,做出不同的響應動作。
這樣其實是不太好的,因為這會使這個動作函式內部去維護一些判斷邏輯,如果flag引數比較多,函式內部的區分情況也會很多。
另外這裡也涉及一種思想:具體的差異實現應該由使用者提供,而不是統一執行者去維護。
或者稱之為依賴倒置原則:高層模組(列印)不應該依賴於實現細節(某個人的喜好)。
比如,我現在有一臺印表機