-
使用有准确意义的变量名
-
在变量值不会改变时使用const声明一个常量
-
对同一类型的变量使用相同的词汇
-
使用可搜索的名称(用var声明全局的大写变量)
-
使用解释型的变量
bad:
const cityStateRegex = /^(.+)[,\\s]+(.+?)\s*(\d{5})?$/;
saveCityState(cityStateRegex.match(cityStateRegex)[1], cityStateRegex.match(cityStateRegex)[2]);
good:
const cityStateRegex = /^(.+)[,\\s]+(.+?)\s*(\d{5})?$/;
const match = cityStateRegex.match(cityStateRegex)
const city = match[1];
const state = match[2];
saveCityState(city, state);
- 短路语法比条件语句更清晰
- 函数参数理论上少于等于2个
- 一个函数只做一件事
- 函数名称要说明他做的事
- 函数应该只抽象一个层次
- 删除重复代码
- 使用默认参数代替短路表达式
bad:
function writeForumComment(subject, body) {
subject = subject || 'No Subject';
body = body || 'No text';
}
good:
function writeForumComment(subject = 'No subject', body = 'No text') {
...
}
- 用Object.assign设置默认对象
config = Object.assign({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
}, config);
- 不要把标记用作函数参数(Boolean值)
bad:
function createFile(name, temp) {
if (temp) {
fs.create('./temp/' + name);
} else {
fs.create(name);
}
}
good:
function createTempFile(name) {
fs.create('./temp/' + name);
}
function createFile(name) {
fs.create(name);
}
- 避免否定条件
- 封装条件
bad:
if (fsm.state === 'fetching' && isEmpty(listNode)) {
/// ...
}
good:
function shouldShowSpinner(fsm, listNode) {
return fsm.state === 'fetching' && isEmpty(listNode);
}
if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
// ...
}
- 避免副作用
函数参数名和全局变量一样时,将全局变量置于函数之后
18. 喜欢上命令式编程之上的函数式编程
bad:
const programmerOutput = [
{
name: 'Uncle Bobby',
linesOfCode: 500
}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];
var totalOutput = 0;
for (var i = 0; i < programmerOutput.length; i++) {
totalOutput += programmerOutput[i].linesOfCode;
}
good:
const programmerOutput = [
{
name: 'Uncle Bobby',
linesOfCode: 500
}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];
var totalOutput = programmerOutput
.map((programmer) => programmer.linesOfCode)
.reduce((acc, linesOfCode) => acc + linesOfCode, 0);
- 避免条件
- 避免类型检查
- 不要过度优化
bad:
for (var i = 0, len = list.length; i < len; i++) {
// ...
}
good:
for (var i = 0; i < list.length; i++) {
// ...
}
- 删除不用的代码(不要注释代码)
- 使用getter和setter
bad:
class BankAccount {
constructor() {
this.balance = 1000;
}
}
let bankAccount = new BankAccount();
// 支出
bankAccount.balance = bankAccount.balance - 100;
good:
class BankAccount {
constructor() {
this.balance = 1000;
}
// It doesn't have to be prefixed with `get` or `set` to be a getter/setter
withdraw(amount) {
if (verifyAmountCanBeDeducted(amount)) {
this.balance -= amount;
}
}
}
let bankAccount = new BankAccount();
bankAccount.withdraw(100);
- 让对象拥有私有成员(通过函数return)
bad:
var Employee = function(name) {
this.name = name;
}
Employee.prototype.getName = function() {
return this.name;
}
var employee = new Employee('John Doe');
console.log('Employee name: ' + employee.getName()); // Employee name: John Doe
delete employee.name;
console.log('Employee name: ' + employee.getName()); // Employee name: undefined
good:
var Employee = (function() {
function Employee(name) {
this.getName = function() {
return name;
};
}
return Employee;
}());
var employee = new Employee('John Doe');
console.log('Employee name: ' + employee.getName()); // Employee name: John Doe
delete employee.name;
console.log('Employee name: ' + employee.getName()); // Employee name: John Doe
- 类-单一职责原则(SRP)
- 开放封装原则(OCP)
- 里氏替换原则(LSP)
- 接口隔离原则(ISP)
- 依赖倒置原则(DIP)
- async/await
bad:(promise)
require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
.then(function(response) {
return require('fs-promise').writeFile('article.html', response);
})
.then(function() {
console.log('File written');
})
.catch(function(err) {
console.error(err);
})
good:
async function getCleanCodeArticle() {
try {
var request = await require('request-promise')
var response = await request.get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin');
var fileHandle = await require('fs-promise');
await fileHandle.writeFile('article.html', response);
console.log('File written');
} catch(err) {
console.log(err);
}
}
- 错误处理
try {
functionThatMightThrow();
} catch (error) {
// 选择之一(比 console.log 更闹心):
console.error(error);
// 另一个选择:
notifyUserOfError(error);
// 另一个选择:
reportErrorToService(error);
// 或者所有上述三种选择!
}
- 使用一致的大小写
- 调用者和被调用者尽可能的放在一起
- 删除已注释代码及尽量少使用注释
- 做有意义的区分,依义命名
不要使用如a1,a2,a3…这样没有区分度的命名,用parent,children等有意义的区分
36. 不要使用双关语
如add,使用append或insert这类动词
37. 变量,函数,类的命名应该尽量简短,有具体意义(data,info都是一个意思)