摘要:如何提高代碼的可讀性復(fù)用性擴(kuò)展性。嚴(yán)格遵守這條規(guī)則會讓你的代碼可讀性更好,也更容易重構(gòu)。如果違反這個(gè)規(guī)則,那么代碼會很難被測試或者重用。它讓你的代碼簡潔優(yōu)雅。
原文:https://github.com/ryanmcderm...
說明:本文翻譯自 github 上的一個(gè)項(xiàng)目,非全文搬運(yùn),只取部分精華。
如何提高代碼的可讀性、復(fù)用性、擴(kuò)展性。我們將從以下四個(gè)方面討論:
變量
函數(shù)
類
異步
一、變量 用有意義且常用的單詞命名// Bad: const yyyymmdstr = moment().format("YYYY/MM/DD"); // Good: const currentDate = moment().format("YYYY/MM/DD");保持統(tǒng)一
對同一類型的變量使用相同的命名保持統(tǒng)一:
// Bad: getUserInfo(); getClientData(); getCustomerRecord(); // Good: getUser()每個(gè)常量(全大寫)都該命名
可以用 ESLint 檢測代碼中未命名的常量。
// Bad: // 其他人知道 86400000 的意思嗎? setTimeout( blastOff, 86400000 ); // Good: const MILLISECOND_IN_A_DAY = 86400000; setTimeout( blastOff, MILLISECOND_IN_A_DAY );避免無意義的命名
既然創(chuàng)建了一個(gè) car 對象,就沒有必要把它的顏色命名為 carColor。
// Bad: const car = { carMake: "Honda", carModel: "Accord", carColor: "Blue" }; function paintCar( car ) { car.carColor = "Red"; } // Good: const car = { make: "Honda", model: "Accord", color: "Blue" }; function paintCar( car ) { car.color = "Red"; }傳參使用默認(rèn)值
// Bad: function createMicrobrewery( name ) { const breweryName = name || "Hipster Brew Co."; // ... } // Good: function createMicrobrewery( name = "Hipster Brew Co." ) { // ... }二、函數(shù) 函數(shù)參數(shù)( 最好 2 個(gè)或更少 )
如果參數(shù)超過兩個(gè),建議使用 ES6 的解構(gòu)語法,不用考慮參數(shù)的順序。
// Bad: function createMenu( title, body, buttonText, cancellable ) { // ... } // Good: function createMenu( { title, body, buttonText, cancellable } ) { // ... } createMenu({ title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true });一個(gè)方法只做一件事情
這是一條在軟件工程領(lǐng)域流傳久遠(yuǎn)的規(guī)則。嚴(yán)格遵守這條規(guī)則會讓你的代碼可讀性更好,也更容易重構(gòu)。如果違反這個(gè)規(guī)則,那么代碼會很難被測試或者重用。
// Bad: function emailClients( clients ) { clients.forEach( client => { const clientRecord = database.lookup( client ); if ( clientRecord.isActive() ) { email( client ); } }); } // Good: function emailActiveClients( clients ) { clients .filter( isActiveClient ) .forEach( email ); } function isActiveClient( client ) { const clientRecord = database.lookup( client ); return clientRecord.isActive(); }函數(shù)名上體現(xiàn)它的作用
// Bad: function addToDate( date, month ) { // ... } const date = new Date(); // 很難知道是把什么加到日期中 addToDate( date, 1 ); // Good: function addMonthToDate( month, date ) { // ... } const date = new Date(); addMonthToDate( 1, date );刪除重復(fù)代碼,合并相似函數(shù)
很多時(shí)候雖然是同一個(gè)功能,但由于一兩個(gè)不同點(diǎn),讓你不得不寫兩個(gè)幾乎相同的函數(shù)。
// Bad: function showDeveloperList(developers) { developers.forEach((developer) => { const expectedSalary = developer.calculateExpectedSalary(); const experience = developer.getExperience(); const githubLink = developer.getGithubLink(); const data = { expectedSalary, experience, githubLink }; render(data); }); } function showManagerList(managers) { managers.forEach((manager) => { const expectedSalary = manager.calculateExpectedSalary(); const experience = manager.getExperience(); const portfolio = manager.getMBAProjects(); const data = { expectedSalary, experience, portfolio }; render(data); }); } // Good: function showEmployeeList(employees) { employees.forEach(employee => { const expectedSalary = employee.calculateExpectedSalary(); const experience = employee.getExperience(); const data = { expectedSalary, experience, }; switch(employee.type) { case "develop": data.githubLink = employee.getGithubLink(); break case "manager": data.portfolio = employee.getMBAProjects(); break } render(data); }) }使用 Object.assign 設(shè)置默認(rèn)屬性
// Bad: const menuConfig = { title: null, body: "Bar", buttonText: null, cancellable: true }; function createMenu(config) { config.title = config.title || "Foo"; config.body = config.body || "Bar"; config.buttonText = config.buttonText || "Baz"; config.cancellable = config.cancellable !== undefined ? config.cancellable : true; } createMenu(menuConfig); // Good: const menuConfig = { title: "Order", // 不包含 body buttonText: "Send", cancellable: true }; function createMenu(config) { config = Object.assign({ title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true }, config); // config : {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } createMenu(menuConfig);盡量不要寫全局方法
在 JavaScript 中,永遠(yuǎn)不要污染全局,會在生產(chǎn)環(huán)境中產(chǎn)生難以預(yù)料的 bug。舉個(gè)例子,比如你在 Array.prototype 上新增一個(gè) diff 方法來判斷兩個(gè)數(shù)組的不同。而你同事也打算做類似的事情,不過他的 diff 方法是用來判斷兩個(gè)數(shù)組首位元素的不同。很明顯你們方法會產(chǎn)生沖突,遇到這類問題我們可以用 ES2015/ES6 的語法來對 Array 進(jìn)行擴(kuò)展。
// Bad: Array.prototype.diff = function diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); }; // Good: class SuperArray extends Array { diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); } }盡量別用“非”條件句
// Bad: function isDOMNodeNotPresent(node) { // ... } if (!isDOMNodeNotPresent(node)) { // ... } // Good: function isDOMNodePresent(node) { // ... } if (isDOMNodePresent(node)) { // ... }不要過度優(yōu)化
現(xiàn)代瀏覽器已經(jīng)在底層做了很多優(yōu)化,過去的很多優(yōu)化方案都是無效的,會浪費(fèi)你的時(shí)間。
// Bad: // 現(xiàn)代瀏覽器已對此( 緩存 list.length )做了優(yōu)化。 for (let i = 0, len = list.length; i < len; i++) { // ... } // Good: for (let i = 0; i < list.length; i++) { // ... }刪除棄用代碼
這里沒有實(shí)例代碼,刪除就對了
三、類 使用 ES6 的 class在 ES6 之前,沒有類的語法,只能用構(gòu)造函數(shù)的方式模擬類,可讀性非常差。
// Good: // 動物 class Animal { constructor(age) { this.age = age }; move() {}; } // 哺乳動物 class Mammal extends Animal{ constructor(age, furColor) { super(age); this.furColor = furColor; }; liveBirth() {}; } // 人類 class Human extends Mammal{ constructor(age, furColor, languageSpoken) { super(age, furColor); this.languageSpoken = languageSpoken; }; speak() {}; }使用鏈?zhǔn)秸{(diào)用
這種模式相當(dāng)有用,可以在很多庫中都有使用。它讓你的代碼簡潔優(yōu)雅。
class Car { constructor(make, model, color) { this.make = make; this.model = model; this.color = color; } setMake(make) { this.make = make; } setModel(model) { this.model = model; } setColor(color) { this.color = color; } save() { console.log(this.make, this.model, this.color); } } // Bad: const car = new Car("Ford","F-150","red"); car.setColor("pink"); car.save(); // Good: class Car { constructor(make, model, color) { this.make = make; this.model = model; this.color = color; } setMake(make) { this.make = make; // NOTE: Returning this for chaining return this; } setModel(model) { this.model = model; // NOTE: Returning this for chaining return this; } setColor(color) { this.color = color; // NOTE: Returning this for chaining return this; } save() { console.log(this.make, this.model, this.color); // NOTE: Returning this for chaining return this; } } const car = new Car("Ford", "F-150", "red").setColor("pink").save();四、異步 使用 promise 或者 Async/Await 代替回調(diào)
// Bad: get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin", (requestErr, response) => { if (requestErr) { console.error(requestErr); } else { writeFile("article.html", response.body, (writeErr) => { if (writeErr) { console.error(writeErr); } else { console.log("File written"); } }); } }); // Good: get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") .then((response) => { return writeFile("article.html", response); }) .then(() => { console.log("File written"); }) .catch((err) => { console.error(err); }); // perfect: async function getCleanCodeArticle() { try { const response = await get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin"); await writeFile("article.html", response); console.log("File written"); } catch(err) { console.error(err); } }后記
如果你想進(jìn)【大前端交流群】,關(guān)注公眾號點(diǎn)擊“交流加群”添加機(jī)器人自動拉你入群。關(guān)注我第一時(shí)間接收最新干貨。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/105035.html
摘要:這是一個(gè)用于構(gòu)建響應(yīng)式應(yīng)用和網(wǎng)站的前端框架。是基于設(shè)計(jì)的一套豐富的組件。這是一個(gè)對混合式手機(jī)應(yīng)用框架的擴(kuò)展庫。到目前為止它僅大小,而且不依賴于任何第三方的插件,它可以很輕量的被用來創(chuàng)建和應(yīng)用。 _Material design_是Google開發(fā)的,目的是為了統(tǒng)一公司的web端和手機(jī)端的產(chǎn)品風(fēng)格。它是基于很多的原則,比如像合適的動畫,響應(yīng)式,以及顏色和陰影的使用。完整的指南詳情請看這里...
摘要:這是一個(gè)用于構(gòu)建響應(yīng)式應(yīng)用和網(wǎng)站的前端框架。是基于設(shè)計(jì)的一套豐富的組件。這是一個(gè)對混合式手機(jī)應(yīng)用框架的擴(kuò)展庫。到目前為止它僅大小,而且不依賴于任何第三方的插件,它可以很輕量的被用來創(chuàng)建和應(yīng)用。 _Material design_是Google開發(fā)的,目的是為了統(tǒng)一公司的web端和手機(jī)端的產(chǎn)品風(fēng)格。它是基于很多的原則,比如像合適的動畫,響應(yīng)式,以及顏色和陰影的使用。完整的指南詳情請看這里...
摘要:層疊樣式表二修訂版這是對作出的官方說明。速查表兩份表來自一份關(guān)于基礎(chǔ)特性,一份關(guān)于布局。核心第一篇一份來自的基礎(chǔ)參考指南簡寫速查表簡寫形式參考書使用層疊樣式表基礎(chǔ)指南,包含使用的好處介紹個(gè)方法快速寫成高質(zhì)量的寫出高效的一些提示。 迄今為止,我已經(jīng)收集了100多個(gè)精通CSS的資源,它們能讓你更好地掌握CSS技巧,使你的布局設(shè)計(jì)脫穎而出。 CSS3 資源 20個(gè)學(xué)習(xí)CSS3的有用資源 C...
摘要:前端日報(bào)精選譯用搭建探索生命周期中的匿名遞歸瀏覽器端機(jī)器智能框架深入理解筆記和屬性中文上海線下活動前端工程化架構(gòu)實(shí)踐滬江技術(shù)沙龍掘金周二放送追加視頻知乎專欄第期聊一聊前端自動化測試上雙關(guān)語來自前端的小段子,你看得懂嗎眾成翻 2017-08-10 前端日報(bào) 精選 [譯] 用 Node.js 搭建 API Gateway探索 Service Worker 「生命周期」JavaScript ...
閱讀 1711·2021-11-22 12:09
閱讀 1451·2019-08-30 13:22
閱讀 2083·2019-08-29 17:00
閱讀 2635·2019-08-29 16:28
閱讀 2945·2019-08-26 13:51
閱讀 1174·2019-08-26 13:25
閱讀 3238·2019-08-26 12:14
閱讀 3006·2019-08-26 12:14