原文:github.com/ryanmcdermo…
說明:本文翻譯自 github 上的一個項目,非全文搬運,只取部分精華。javascript
如何提升代碼的可讀性、複用性、擴展性。咱們將從如下四個方面討論:html
// Bad:
const yyyymmdstr = moment().format('YYYY/MM/DD');
// Good:
const currentDate = moment().format('YYYY/MM/DD');
複製代碼
對同一類型的變量使用相同的命名保持統一:前端
// Bad:
getUserInfo();
getClientData();
getCustomerRecord();
// Good:
getUser()
複製代碼
能夠用 ESLint
檢測代碼中未命名的常量。java
// Bad:
// 其餘人知道 86400000 的意思嗎?
setTimeout( blastOff, 86400000 );
// Good:
const MILLISECOND_IN_A_DAY = 86400000;
setTimeout( blastOff, MILLISECOND_IN_A_DAY );
複製代碼
既然建立了一個 car 對象,就沒有必要把它的顏色命名爲 carColor。node
// 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 的解構語法,不用考慮參數的順序。git
// Bad:
function createMenu( title, body, buttonText, cancellable ) {
// ...
}
// Good:
function createMenu( { title, body, buttonText, cancellable } ) {
// ...
}
createMenu({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
});
複製代碼
這是一條在軟件工程領域流傳久遠的規則。嚴格遵照這條規則會讓你的代碼可讀性更好,也更容易重構。若是違反這個規則,那麼代碼會很難被測試或者重用。github
// 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 );
複製代碼
不少時候雖然是同一個功能,但因爲一兩個不一樣點,讓你不得不寫兩個幾乎相同的函數。數組
// 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 進行擴展。promise
// 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)) {
// ...
}
複製代碼
現代瀏覽器已經在底層作了不少優化,過去的不少優化方案都是無效的,會浪費你的時間。瀏覽器
// 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);
}
}
複製代碼
若是你想進【大前端交流羣】,關注公衆號點擊「交流加羣」添加機器人自動拉你入羣。關注我第一時間接收最新干貨。