一、变量
传参使用默认值
1 2 3 4 5 6 7 8 9 10
| function createMicrobrewery( name ) { const breweryName = name || 'Hipster Co.'; }
function createMicrobrewery( name = 'Hipster Co.' ) { }
|
避免无意义的命名
既然创建了一个car对象,就没有必要把它的颜色命名为 carColor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' }; function paintCar( car ) { car.carColor = 'Red'; }
const car = { make: 'Honda', model: 'Accord', color: 'Blue' }; function paintCar( car ) { car.color = 'Red'; }
|
二、函数
函数参数
如果参数超过两个,就使用ES6的解构语法,不用考虑参数的顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function createMenu( title, body, buttonText, cancellable ) { }
function createMenu( { title, body, buttonText, cancellable } ) { }
createMenu({ title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true })
|
一个方法只做一件事
这是一条编程领域流传久远的规则。严格遵守这条规则会让你的代码可读性更好,也更容易重构。如果违反这个原则,那么代码会很难被测试或者重用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function emailClients( clients ) { clients.forEach( client => { const clientRecord = database.lookup( client ); if ( clientRecord.isActive() ) { email( client ); } }); }
function emailActiveClients( clients ) { clients .filter( isActiveClient ) .forEach( email ); } function isActiveClient( client ) { const clientRecord = database.lookup( client ); return clientRecord.isActive(); }
|
函数名上体现它的作用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function addToDate( date, month ) { } const date = new Date();
addToDate( date, 1 );
function addMonthToDate( month, date ) { } const date = new Date(); addMonthToDate( 1, date );
|
删除重复代码,合并相似函数
很多时候虽然是同一个功能,但由于一两个不同点,让你不得不写两个几乎相同的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 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); }); }
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 设置默认属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 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);
const menuConfig = { title: 'Order', buttonText: 'Send', cancellable: true }; function createMenu(config) { config = Object.assign({ title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true }, config); } createMenu(menuConfig);
|
不要过度优化
现代浏览器已经在底层做了很多优化,过去的很多优化方案都是无效的,会浪费你的时间
1 2 3 4 5 6 7 8 9 10
|
for (let i = 0, len = list.length; i < len; i++) { }
for (let i = 0; i < list.length; i++) { }
|
三、类
使用 ES6 的class
在 ES6 之前,没有类的语法,只能用构造函数的方式模拟类,可读性非常差。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
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() {}; }
|
使用链式调用
这种模式相当有用,它能让代码更简洁优雅。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| 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); } }
const car = new Car('Ford','F-150','red'); car.setColor('pink'); car.save();
class Car { constructor(make, model, color) { this.make = make; this.model = model; this.color = color; }
setMake(make) { this.make = make; return this; }
setModel(model) { this.model = model; return this; }
setColor(color) { this.color = color; return this; }
save() { console.log(this.make, this.model, this.color); return this; } }
const car = new Car("Ford", "F-150", "red").setColor("pink").save();
|
四、条件式和匹配条件的技巧
多个条件,使用 Array.includes
假设我们想要在函数中检查汽车模型是 renault 还是 peugeot。那么代码可能是这样的:
1 2 3 4 5 6 7
| const checkCarModel = (model) => { if(model === 'renault' || model === 'peugeot') { console.log('model valid'); } }
checkCarModel('renault');
|
考虑到只有两个模型,这样写勉强能接受,但如果我们还想要检查另一个或者是几个模型的话 还得增加更多的 or 语句,那么代码将变得难以维护,且不够整洁。为了让它更整洁,可以这样重写函数:
1 2 3 4 5 6 7
| const checkCarModel = (model) => { if(['peugeot', 'renault'].includes(model)) { console.log('model valid'); } }
checkCarModel('renault');
|
这时候 如果需要检查更多的模型,只需要添加数组的元素就可以了。
提前返回而不是使用 if…else 分支
假设我们想要显示所给的车辆的模型和生产年份:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| const checkModel = (car) => { let result; if(car) { if(car.model) { if(car.year) { result = `车的模型是:${car.model}; 车的年份是:${car.year}`; } else { result = '没有年份' } } else { result = '没有模型' } } else { result = '没有车' } return result; }
console.log(checkModel()); console.log(checkModel({ year: 1999 })); console.log(checkModel({ model: 'ford' })); console.log(checkModel({ model: 'ford',year: 1999 }));
|
本身例子的问题很简单,但是上面的代码太长了。要是有更复杂的逻辑就会出现更多的 if..else 语句。
所以现在要重构函数,使用 ES6 的新特性和多个返回语句,展示一份简洁优雅的代码。
1 2 3 4 5 6 7 8 9 10 11 12
| const checkModel =( {model, year} = {} ) => { if(!model && !year) return '没有车'; if(!model) return '没有模型'; if(!year) return '没有年份';
return `车的模型是:${model}; 车的年份是:${year}`; } console.log(checkModel()); console.log(checkModel({ year: 1999 })); console.log(checkModel({ model: 'ford' })); console.log(checkModel({ model: 'ford', year: 1999 }));
|
重构函数中,使用了解构和默认参数。参数如果传入 null ,函数将会抛出错误。
使用索引或者映射,而不是 switch 语句
假设完美想要基于给定的国家获取汽车模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const getCarsByState = (state) => { switch (state) { case 'usa': return ['Ford', 'Dodge']; case 'france': return ['Renault', 'Peugeot']; case 'italy': return ['Fiat']; default: return []; } }
console.log(getCarsByState()); console.log(getCarsByState('usa')); console.log(getCarsByState('italy'));
|
上述代码可以重构,完全去除 switch 语句
1 2 3 4 5 6 7 8 9 10 11 12
| const cars = new Map() .set('usa', ['Ford', 'Dodge']) .set('france', ['Renault', 'Peugeot']) .set('italy', ['Fiat']);
const getCarsByState = (state) => { return cars.get(state) || []; }
console.log(getCarsByState()); console.log(getCarsByState('usa')); console.log(getCarsByState('italy'));
|
整合自:
https://juejin.im/post/5d11b494518825327a218454
https://juejin.im/post/5d0e11196fb9a07eee5ed6d2