原文: https://github.com/ryanmcderm...
說明:本文翻譯自 github 上的一個項目,非全文搬運,只取部分精華。
如何提升代碼的可讀性、複用性、擴展性。咱們將從如下四個方面討論:javascript
// Bad: const yyyymmdstr = moment().format('YYYY/MM/DD'); // Good: const currentDate = moment().format('YYYY/MM/DD');
對同一類型的變量使用相同的命名保持統一:html
// Bad: getUserInfo(); getClientData(); getCustomerRecord(); // Good: getUser()
能夠用 ESLint
檢測代碼中未命名的常量。前端
// Bad: // 其餘人知道 86400000 的意思嗎? setTimeout( blastOff, 86400000 ); // Good: const MILLISECOND_IN_A_DAY = 86400000; setTimeout( blastOff, MILLISECOND_IN_A_DAY );
既然建立了一個 car 對象,就沒有必要把它的顏色命名爲 carColor。java
// 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'; }
// Bad: function createMicrobrewery( name ) { const breweryName = name || 'Hipster Brew Co.'; // ... } // Good: function createMicrobrewery( name = 'Hipster Brew Co.' ) { // ... }
若是參數超過兩個,建議使用 ES6 的解構語法,不用考慮參數的順序。node
// Bad: function createMenu( title, body, buttonText, cancellable ) { // ... } // Good: function createMenu( { title, body, buttonText, cancellable } ) { // ... } createMenu({ title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true });
這是一條在軟件工程領域流傳久遠的規則。嚴格遵照這條規則會讓你的代碼可讀性更好,也更容易重構。若是違反這個規則,那麼代碼會很難被測試或者重用。git
// 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(); }
// Bad: function addToDate( date, month ) { // ... } const date = new Date(); // 很難知道是把什麼加到日期中 addToDate( date, 1 ); // Good: function addMonthToDate( month, date ) { // ... } const date = new Date(); addMonthToDate( 1, date );
不少時候雖然是同一個功能,但因爲一兩個不一樣點,讓你不得不寫兩個幾乎相同的函數。github
// 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); }) }
// 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 中,永遠不要污染全局,會在生產環境中產生難以預料的 bug。舉個例子,好比你在 Array.prototype 上新增一個 diff 方法來判斷兩個數組的不一樣。而你同事也打算作相似的事情,不過他的 diff 方法是用來判斷兩個數組首位元素的不一樣。很明顯大家方法會產生衝突,遇到這類問題咱們能夠用 ES2015/ES6 的語法來對 Array 進行擴展。數組
// 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)) { // ... }
現代瀏覽器已經在底層作了不少優化,過去的不少優化方案都是無效的,會浪費你的時間。promise
// Bad: // 現代瀏覽器已對此( 緩存 list.length )作了優化。 for (let i = 0, len = list.length; i < len; i++) { // ... } // Good: for (let i = 0; i < list.length; i++) { // ... }
這裏沒有實例代碼,刪除就對了瀏覽器
在 ES6 以前,沒有類的語法,只能用構造函數的方式模擬類,可讀性很是差。
// 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() {}; }
這種模式至關有用,能夠在不少庫中都有使用。它讓你的代碼簡潔優雅。
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();
// 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); } }
若是你想進【大前端交流羣】,關注公衆號點擊「交流加羣」添加機器人自動拉你入羣。關注我第一時間接收最新干貨。