问题:滥用变量javascript
let kpi = 4; // 定义好了以后再也没用过 function example() { var a = 1; var b = 2; var c = a+b; var d = c+1; var e = d+a; return e; }
修改:数据只使用一次或不使用就无需装到变量中vue
let kpi = 4; // 没用的就删除掉,否则过三个月本身都不敢删,怕是否是那用到了 function example() { var a = 1; var b = 2; return 2a+b+1; }
问题:自我感受良好的缩写java
let fName = 'jackie'; // 看起来命名挺规范,缩写,驼峰法都用上,ESlint各类检测规范的工具都经过,But,fName是啥?这时候,你是否是想说What are you 弄啥呢? let lName = 'willen'; // 这个问题和上面的同样
修改:无需对每一个变量都写注释,从名字上就看懂node
let firstName = 'jackie'; // 怎么样,是否是一目了然。少被喷了一次 let lastName = 'willen'; ```
问题:无说明的参数程序员
if (value.length < 8) { // 为何要小于8,8表示啥?长度,仍是位移,仍是高度?Oh,my God!! .... }
修改:添加变量vuex
const MAX_INPUT_LENGTH = 8; if (value.length < MAX_INPUT_LENGTH) { // 一目了然,不能超过最大输入长度 .... }
问题:命名过于啰嗦编程
let nameString;
let theUsers;
修改:作到简洁明了redux
let name;
let users;
问题:长代码不知道啥意思api
const address = 'One Infinite Loop, Cupertino 95014'; const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; saveCityZipCode( address.match(cityZipCodeRegex)[1], // 这个公式到底要干吗,对不起,原做者已经离职了。本身看代码 address.match(cityZipCodeRegex)[2], // 这个公式到底要干吗,对不起,原做者已经离职了。本身看代码 );
修改:用变量名来解释长代码的含义数组
const address = 'One Infinite Loop, Cupertino 95014'; const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; const [, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode);
问题:在不一样的文件不停的定义全局变量
//name.js window.name = 'a'; hello.js window.name = 'b'; time.js window.name = 'c'; //三个文件的前后加载顺序不一样,都会使得window.name的值不一样,同时,你对window.name的修改了都有可能不生效,由于你不知道你修改过以后别人是否是又在别的说明文件中对其的值重置了。因此随着文件的增多,会致使一团乱麻。
修改:少用或使用替代方案
1.能够选择只用局部变量。经过(){}的方法。
2.若是你确实用不少的全局变量须要共享,你可使用vuex,redux或者你本身参考flux模式写一个也行。
问题:对于求值获取的变量,没有兜底。
const MIN_NAME_LENGTH = 8; let lastName = fullName[1]; if(lastName.length > MIN_NAME_LENGTH) { // 这样你就给你的代码成功的埋了一个坑,你有考虑过若是fullName = ['jackie']这样的状况吗?这样程序一跑起来就爆炸。要不你试试。 .... }
修改: 对于求值变量,作好兜底。
const MIN_NAME_LENGTH = 8; let lastName = fullName[1] || ''; // 作好兜底,fullName[1]中取不到的时候,不至于赋值个undefined,至少还有个空字符,从根本上讲,lastName的变量类型仍是String,String原型链上的特性都能使用,不会报错。不会变成undefined。 if(lastName.length > MIN_NAME_LENGTH) { .... } 其实在项目中有不少求值变量,对于每一个求值变量都须要作好兜底。 let propertyValue = Object.attr || 0; // 由于Object.attr有可能为空,因此须要兜底。 可是,赋值变量就不须要兜底了。 let a = 2; // 由于有底了,因此不要兜着。 let myName = 'Tiny'; // 由于有底了,因此不要兜着。
问题:从命名没法知道返回值类型
function showFriendsList() {....} // 如今问,你知道这个返回的是一个数组,仍是一个对象,仍是true or false。你能答的上来否?你能答得上来我请你吃松鹤楼的满汉全席还请你不要当真。
修改:对于返回true or false的函数,最好以should/is/can/has开头
function shouldShowFriendsList() {...} function isEmpty() {...} function canCreateDocuments() {...} function hasLicense() {...}
问题:不要让功能函数的输出变化无常。
function plusAbc(a, b, c) { // 这个函数的输出将变化无常,由于api返回的值一旦改变,一样输入函数的a,b,c的值,但函数返回的结果却不必定相同。 var c = fetch('../api'); return a+b+c; }
修改:功能函数使用纯函数,输入一致,输出结果永远惟一
function plusAbc(a, b, c) { // 一样输入函数的a,b,c的值,但函数返回的结果永远相同。 return a+b+c; }
问题:传参无说明
page.getSVG(api, true, false); // true和false啥意思,一目不了然
修改:传参有说明
page.getSVG({ imageApi: api, includePageBackground: true, // 一目了然,知道这些true和false是啥意思 compress: false, })
问题:没法辨别函数意图
function emlU(user) { .... }
修改:动词开头,函数意图就很明显
function sendEmailToUser(user) { .... }
注意:这是软件工程中最重要的一条规则,当函数须要作更多的事情时,它们将会更难进行编写、测试、理解和组合。当你能将一个函数抽离出只完成一个动做,他们将可以很容易的进行重构而且你的代码将会更容易阅读。若是你严格遵照本条规则,你将会领先于许多开发者。
问题:函数功能混乱,一个函数包含多个功能。最后就像能以一当百的老师傅同样,被乱拳打死(乱拳(功能复杂函数)打死老师傅(老程序员))
function sendEmailToClients(clients) { clients.forEach(client => { const clientRecord = database.lookup(client) if (clientRecord.isActive()) { email(client) } }) }
修改:功能拆解,
function sendEmailToActiveClients(clients) { //各个击破,易于维护和复用 clients.filter(isActiveClient).forEach(email) } function isActiveClient(client) { const clientRecord = database.lookup(client) return clientRecord.isActive() }
问题:使用for循环编程
for(i = 1; i <= 10; i++) { // 一看到for循环让人顿生不想看的情愫 a[i] = a[i] +1; }
修改:使用命令式编程
let b = a.map(item => ++item) // 怎么样,是否是很好理解,就是把a的值每项加一赋值给b就能够了。如今在javascript中几乎全部的for循环均可以被map,filter,find,some,any,forEach等命令式编成取代。
问题:if else过多
if (a === 1) { ... } else if (a ===2) { ... } else if (a === 3) { ... } else { ... }
修改:可使用switch替代或用数组替代
//方法一: switch(a) { case 1: .... case 2: .... case 3: .... default: .... } //方法二 let handler = { 1: () => {....}, 2: () => {....}. 3: () => {....}, default: () => {....} } handler[a]() || handler['default']()
问题:采用传统函数
function foo() { // code }
修改:使用箭头函数
let foo = () => { // code }
问题:采用传统+号
var message = 'Hello ' + name + ', it\'s ' + time + ' now'
修改:采用模板字符
var message = `Hello ${name}, it's ${time} now`
问题:使用传统赋值
var data = { name: 'dys', age: 1 }; var name = data.name; var age = data.age; var fullName = ['jackie', 'willen']; var firstName = fullName[0]; var lastName = fullName[1];
修改:使用结构赋值
const data = {name:'dys', age:1}; const {name, age} = data; // 怎么样,是否是简单明了 var fullName = ['jackie', 'willen']; const [firstName, lastName] = fullName;
问题:采用传统的函数原型链实现继承
//典型的 ES5 的类(function)在继承、构造和方法定义方面可读性较差,当须要继承时,优先选用 class。代码太多,就省略了。
修改:采用ES6类实现继承
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() { /* ... */ } }
先写到这了,这是目前为止发现的问题,这篇文章中并无彻底覆盖到常见的写代码的很差的习惯,因此你若是觉的有须要补充的,均可以在文章下方评论,或者直接到下面的Github的这篇文章中评论。
参考连接:
https://blog.risingstack.com/javascript-clean-coding-best-practices-node-js-at-scale/(JavaScript Clean Coding Best Practices)
https://www.zhihu.com/question/20635785 (如何写出优美的 JavaScript 代码?)