想必你們都有接手過老舊項目,它的代碼風格怎麼樣?可能大部分同窗都會無力吐槽吧。筆者認爲一份代碼的好壞,先無論其實現如何,至少其 可讀性 得保證,才能算得上好代碼。有些尚未意識到 可讀性代碼 所帶來好處的同窗,可能常常會遇到上週才寫的代碼,今天打開項目一看,臥槽,這個 💩 同樣的代碼是我寫的嗎?css
筆者的 代碼潔癖 有點嚴重,因此平時對本身寫的代碼也有比較高的要求,至少在 可讀性 上算是比較能保證。下面將分享一些代碼 可讀性 和 簡潔性 方面的一些技巧。前端
相信你們比較多的吐槽就是變量的命名,以致於出現相似 CodeIf 這種輔助聲明變量名的神器,因此平時在項目中如何作到好的命名呢。git
其實大多數的變量賦值後都不會再改變(從新賦值),因此筆者會優先使用
const
而不是let
,確實沒法避免須要賦值屢次才用let
。github
// Bad
static({
maxAge: 28800000, // what ???
});
// Good
const EIGHT_HOURS_IN_MILLISECOND = 28800000;
// or
const EIGHT_HOURS_IN_MILLISECOND = 8 * 60 * 60 * 1000;
static({
maxAge: EIGHT_HOURS_IN_MILLISECOND,
});
// Bad
$(document).on('keydown', event => {
// 27 是什麼鬼???
if(event.keyCode === 27) {
// do something ...
}
});
// Good
$(document).on('keydown', event => {
const KEY_ESC = 27;
if(event.keyCode === KEY_ESC) {
// do something ...
}
});
複製代碼
// Bad
const n = '大板慄';
const a = 18;
// Good
const name = '大板慄';
const age = 18;
複製代碼
// Bad
const favoriteList = [];
const getCurrentUserData = () => {};
// Good
const favorites = [];
const getCurrentUser = () => {};
複製代碼
單看函數名就應該知道功能是什麼。編程
// Bad
function fetchAtls() {}
// Good
function fetchArticles() {}
// or
function getArticles() {}
複製代碼
利用三目運算符和 ES6+ 語法簡化代碼app
// Bad
$('.js-button').on('click', function() {
var name = '開始';
if ($(this).hasClass('again')) {
name = '再玩一次';
}
app.track('按鈕', name);
});
// Good
$('.js-button').on('click', function() {
const again = $(this).hasClass('again');
app.track(again ? '再玩一次' : '開始');
});
// Bad
const celebrationDayChange = isSameDay => {
if (isSameDay) {
$dateSelect.addClass('hide');
} else {
$dateSelect.removeClass('hide');
}
};
// Good
const celebrationDayChange = isSameDay => {
const action = isSameDay ? 'addClass' : 'removeClass';
$dateSelect[action]('hide');
};
複製代碼
函數的參數儘可能簡短,若有 3 個以上建議直接換成對象的方式:ide
// Bad
function publish(title, author, except, content) {}
// 必須知道參數位置信息
publish('title', '大板慄', 'an excellent article', 'This is content.');
// Good
function publish({title, author, except, content}) {}
publish({
title: 'title',
author: '大板慄',
except: 'an excellent article',
content: 'This is content.',
});
複製代碼
// Bad
const options = {
name: '大板慄',
logo: 'Logo.png',
theme: 'dark',
};
function createApp(options = {}) {
options.name = options.name || 'App';
options.logo = options.logo || 'Logo.png';
options.theme = options.theme || 'light';
}
// Good
function createApp(options = {}) {
options = Object.assign({
name: 'App',
logo: 'Logo.png',
theme: 'light',
}, options);
}
複製代碼
// Bad
function App(name) {
name = name || 'App';
// ...
}
// Good
function App(name = 'App') {
// ...
}
複製代碼
// Bad
function querify(object = {}) {
const keys = Object.keys(object);
let result = '';
for(let i = 0; i < keys.length; i++) {
result += `&${keys[i]}=${object[keys[i]]}`;
}
result = result.slice(1);
return result;
}
// Good
function querify(object = {}) {
const keys = Object.keys(object);
const result = keys.reduce((prev, current) => {
prev += `&${current}=${object[current]}`;
return prev;
}, '').slice(1);
return result;
}
複製代碼
// Bad
function reducer(state = 0, {type}) {
switch (type) {
case 'INCREASE':
return state + 1;
case 'DECREASE':
return state - 1;
default:
return state;
}
}
// Good
function reducer(state = 0, {type}) {
const mapping = {
'INCREASE': state + 1,
'DECREASE': state - 1,
};
const effective = Object.keys(mapping).includes(type);
return effective ? mapping[type] : state;
}
複製代碼
下面是筆者寫的 自動爲背景圖片添加寬高 的 PostCSS 插件中的 代碼片斷:函數
// Bad
if (/background[^:]*.*url[^;]+/gi.test(ruleString)) {
const [originURL, URL] = getImageURL(ruleString);
// ...
}
// Good
const hasBackground = rule => /background[^:]*.*url[^;]+/gi.test(rule);
if (hasBackground(ruleString)) {
const [originURL, URL] = getImageURL(ruleString);
// ...
}
複製代碼
函數是最小可複用單元,因此若是一個函數作了多個事情的話,表明這個函數難以被複用,So, just do one thing.工具
// Bad
function notify(users) {
users.map(user => {
const record = DB.find(user);
if (record.isActive()) {
sendMessage(user);
}
});
}
// Good
// judge activation only
function isActive(user) {
const record = DB.find(user);
return record.isActive();
}
function notify(users) {
users.filter(isActive).forEach(sendMessage);
}
複製代碼
// Bad
const isNotSupport = () => {};
const canNotUpdate = () => {};
// Good
const isSupport = () => {};
const canUpdate = () => {};
複製代碼
// Bad
const first = items[0];
const second = items[1];
const name = me.name;
const age = me.age;
// Good
const [first, second] = items;
const { name, age } = me;
// Bad
function App(options) {
track({
name: options.name,
version: options.version,
env: options.env,
});
}
// Good
// 解構函數參數
function App({name, version, env}) {
track({
name: name,
version: version,
env: env,
});
}
// Best
function App({name, version, env}) {
// 使用對象簡寫
track({ name, version, env });
}
複製代碼
// Bad
const greeting = name => 'Hello ' + name + '!';
// Good
const greeting = name => `Hello ${name}!`;
複製代碼
// Bad
function greeting(name) {
return `Hello ${name}!`;
}
// Good
const greeting = name => `Hello ${name}!`;
複製代碼
// Bad
fetchCurrentUser((error, currentUser) => {
if(error) throw Error;
fetchArticles(currentUser.id, (error, articles) => {
if(error) throw Error;
// articles here...
});
});
// Good
fetchCurrentUser
.then(currentUser => currentUser.id)
.then(fetchArticles)
.then(articles => {
// articles here...
})
.catch(() => {
throw Error;
});
// Best
try {
const currentUser = await fetchCurrentUser();
const articles = await fetchArticles(currentUser.id);
// articles here...
} catch() {
throw Error;
}
複製代碼
長而具備描述性的名稱,要比短而使人費解的名稱好,也比描述性的長註釋更好,好的代碼是 自注釋 的,不要擔憂變量名太長(打包工具壓縮後都同樣)。post
代碼不僅是寫給機器看的,也是寫給人看的,因此從如今開始編寫 可讀性強、易維護 的代碼吧。
最後友情提醒你們 代碼千萬行,註釋第一行。編程不規範,同事兩行淚。