1. 前言
ES6 新增了很多语法和语法糖,在使用这些语法和语法糖的时候可以让我们的代码更加优雅整洁。另外,在程序上有一些约定俗成的东西,这样会帮助我们更好地书写和阅读代码。本文我们将学习前端代码的整洁之道帮助你更好地书写你的代码。
2. 变量的使用
2.1 命名
在定义变量时最好使用驼峰命名(如:aaBbCc)的方式,并且要使用有准确意义的变量名,这样容易阅读。
// bad var getname = function() { return 'mybj123'; } // good var getName = function() { return 'mybj123'; }
在声明变量时不要添加没必要的上下文,如果你的类名称 / 对象名称已经说明了它们是什么,不要在 (属性) 变量名里重复。
// bad const dog = { dogType: '金毛犬' dogColor: '黄色', }; dog.dogType = '柯基' // good const dog = { type: '金毛犬' color: '黄色', }; dog.type = '柯基犬'
2.2 let 和 const 的选择
ES6 提出了两个新的声明变量的命令:let
和const
用于代替var
,使用let
来声明可变变量,使用const
来声明常量。对于全局环境下的常量,变量名可以使用纯大写加下划线的方式命名。
let name = 'zhangsan'; name = 'lisi'; const PI_COUNT = 3.14; { const lession = 'ES6 Mybj'; console.log(lession); }
在选择let
和const
时,优先使用const
,尤其是在全局环境,不应该设置变量,只应设置常量。
const
比let
好的几个原因:
- 不会对值产生副作用,也就是值被修改,告诉开发者此变量不能被修改;
const
比较符合函数式编程思想,运算不改变值,只是新建值;- JavaScript 编译器会对
const
进行优化,所以多使用const
,有利于提高程序的运行效率,也就是说let
和const
的本质区别,其实是编译器内部的处理不同。
在作用域内声明的变量需要使用,如果下文没有用到就不要声明。
// bad const name = 'xiaoming'; // 下文没有使用就不要定义了 // good const name = 'xiaoming'; console.log(name);
2.3 字符串
对于静态字符串一律使用单引号,不使用双引号。在拼接字符串的时候需要使用反引号的方式,更加易于阅读。
// bad const name = "mybj123"; const info = name + ' ES6 lesson'; // good const name = 'mybj123'; const info = `${name} ES6 lesson`;
2.4 解构赋值
在批量定义有默认值的变量时可以使用数组的解构赋值。
// bad const a = 1, b = 2, c = 3; // good const [a, b, c] = [1, 2, 3];
在获取数组或对象中值时也可以优先使用解构的方式:
const arr = [1, 2, 3, 4]; const obj = {a: 1, b: 3}; // bad const x = arr[0]; const y = arr[1]; const a = obj.a; const b = obj.b; // good const [x, y] = arr; const [a, b] = obj;
在函数参数中,如果函数接收的参数是一个对象时,可以直接在函数的括号中解构对象,这样可以在函数内部之间使用变量。
// bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; } // good function getFullName(obj) { const { firstName, lastName } = obj; } // best function getFullName({ firstName, lastName }) {}
对于函数中有返回值是对象时,对象中属性名和要返回的变量名相同时可以省了变量。
// bad function foo() { const a = 'aaa'; const b = 'bbb'; return { a: a, b: b } } // good function foo() { const a = 'aaa'; const b = 'bbb'; return { a, b } }
2.5 尽量减少使用条件语法
在条件语句中,可以使用或(||
)运算符来设置有默认值的变量。
// bad function createPerson(name) { var newName; if (name) { newName = name; } else { newName = 'Jack'; } } // good function createPerson(name) { const newName = name || 'Jack'; }
如果符合条件运算符(?:
)那就尽量使用条件运算符。
const age = 26; // bad let status = '' if (age > 18) { status = '成年人' } else { status = '未成年' } // good const status = age > 18 ? '成年人' : '未成年';
3. 函数
3.1 使用箭头函数
在定义匿名函数时最好使用箭头函数的形式,更加简洁。
// bad const foo = function(){} (function() { console.log('100') })() // good const foo = () => {} (() => { console.log('100') })() // best [1, 2, 3].map(x => x * x);
当函数只有一个参数,并且返回值是一个表达式时,可以将参数外的括号和表达式外的大括号都省略。
// bad [1, 2, 3].map((x) => { return x * x; }); // good [1, 2, 3].map(x => x * x);
使用箭头函数的另一个好处是,在箭头函数内部是不绑定 this
的,这样在调用函数时 this
的指向是不会变的。
var title = "全局标题"; // bad var mybj = { title: " ES6 教程", getTitle : function(){ console.log(this.title); } }; mybj.getTitle(); // ES6 教程 var bar = mybj.getTitle; bar(); // 全局标题 // good var mybj = { title: " ES6 教程", getTitle : () => { console.log(this.title); } }; mybj.getTitle(); // 全局标题 var bar = mybj.getTitle; bar(); // 全局标题
3.2 函数参数
在函数传参时,参数不要超过两个,这样会让你更容易测试这个函数,如果超过 2 个参数会导致组合膨胀,以至于你必须根据不同的参数对大量不同的情况进行测试。理想情况下是两个,如果参数过多可以使用对象来处理。
// bad function fn(a,b,c,d) { // todo } // good const params = { a: 1, b: 2, c: 3, d: true } function fn(params) { // todo }
不要使用函数的内部的参数 arguments
来获取函数的不定参数,使用 ...
来接收。因为 arguments
获取的参数是一个类数组需要转化为真正的数组。
// bad function foo() { const args = [].slice.call(arguments); console.log(args) } foo(1,2,3); // [1,2,3] // good function foo(...args) { console.log(args) } foo(1,2,3); // [1,2,3]
当函数的参数有默认值时,可以使用最短路径的方法设置。
// bad function foo(a, b) { a = a || 1; b = b || 2; } // good function foo(a=1, b=2) { // todo }
3.3 一个函数只做一件事
一个函数最好只做一件事,这是软件工程中最重要的原则。如果函数做了较多的事情,它就难以组合、测试和推测。当你让函数只做一件事情的时候,它们就很容易重构,而且代码读起来也会清晰得多。
// bad function foo(params) { params.forEach(param => { let param1 = fun1(param); if (param1.isActive) { email(client); } }); } // good function foo(params) { params.forEach(param => { step1(param) }); } function step1(param) { if (foo2(param)) { email(client); } } function step2(param) { return fun1(param).isActive }
上文中我们提到了在定义变量时要有意义,从命名就可以知道表达什么意思,所以在定义函数名时要有意义。
// bad function foo() {} // good function setTitle() {}
4. 小结
本文我们从几个方向入手通过好的写法与不好的写法进行对比,可以窥探到程序的优雅,多使用好的规范的写法养成代码规范的好习惯。