代码风格
- 导出的默认函数使用驼峰命名、文件名与函数完全一致。
- 导出单例、函数库、空对象时使用帕斯卡式命名(帕斯卡式命名法是在命名的时候将首字母大写, 如: DisplayInfo)。
类型和变量
1. 变星必须显式声明作用域
- var => 用于声明全局变量或函数级变量
- let => 用于声明块级的局部变量
- const => 声明块级域的只读局部变量。
在ES6中, const代表一个值的“常量索引”, 换句话说, 变量名字在内存中的指针不能够改变, 但是指向这个变量的值可能改变。
2. 尽量对所有的引用使用const, 不要使用var。 如果你一定需要使用可变动的引用, 使用let代替var。
说明:
const和let的作用域更小, 写代码更容易控制。 const可确保无法对引用重新赋值, const引用的指针不变, 重新赋值会报错, 避免不小心的重新赋值给覆盖了。
3. 将所有的const和let分组
4. 在需要的地方给变量 赋值, 但请把它们放在一个合理的位置。
说明:
let和const是作用域而不是函数作用域, 不用担心变量定义会被前移导致问题, 把变量的赋值和调用代码放在一起会使逻辑更加清晰, 可读性更好。
对象和引用
1. 创建有动态属性名的对象时, 尽量在一个地方定义对象的所有属性。
2. 使用对象方法的简写。
说明:
ES6中, 对象字面量被增强了, 写法更加简洁与灵活, 同时在定义对象的时候, 能够做的事件更多了。
例如:
const atom = {
value: 1,
addValue(value) {
return actom.value + value;
}
};
使用对象属性的简写
`const a = 'a';
NG:
const obj = {
a: a,
};
GOOD:
const obj = {
a,
};
数组
1. 使用扩展运算符 ...
复制数组
说明:
扩展运算符可以减少赋值语句的使用, 或者减少通过下标访问数组或对象的方式, 使用代码更加简洁优雅, 可读性更佳。
NG
const len = items.length;
const itemsCopy = [];
let i;
for(i=0; i
Good (一行代码就可以了!)
const itemsCopy = [...items];
属性
使用 .
来访问对象的属性, 只有属性是动态的时候使用 [ ]
。
逗号、分号
- 逗号写在行尾, 并且增加结尾的逗号。
- 使用分号, 以分号作为语句的结束符。
NG
const obj = {
firstName: 'Dana',
lastName: 'Scally'
};
Good
const obj = {
firstName: 'Dana',
lastName: Scally',
};
函数
1. 使用函数声明代替函数表达式
说明:
因为函数声明是可命名的, 所以他们在调用栈中更容易被识别。 此外, 函数声明会把整个函数提升, 而函数表达式只会把函数引用的变量名提升。 这条规则使得箭头函数可以取代函数表达式。
2. 不要使用arguments, 可以选择rest语法 ...
替代。
说明:
使用 ...
能明确你要传入的参数, 另外, rest语法参数是一个真正的数组, 而arguments是一个类数组。
NG:
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join(' ');
}
Good:
function concatenateAll(...args) {
return args.join(' ');
}
3. 直接给函数的参数指定默认值, 不要使用一个变化的函数参数。
4. 直接给函数参数赋值时, 需要避免副作用。
代码块
1. 使用大括号包裹所有的多行代码块。
2. 如果通过if和else使用多行代码块, 把else放在if代码块关闭括号的同一行。
eg:
if(arg) {
return arg;
} else {
return false;
}
模块
1. 代码中总是使用ES6标准的模块(import/export)方式, 而不是使用非标准的模块加载器。
2. 不要使用通配符 *
的import
。
说明:
这样可以确保被import的模块只有一个默认的export项。
3. 不要从import中直接export.
NG:
export {es6 as defaults} from './ablier.js';
Good:
import {es6} from './ablier.js';
export default es6;
4. 如果你的文件只输出一个类, 那你的文件名必须和类名完全保持一致。
import CheckBox from './CheckBox';
箭头函数
1. 别保存this的引用, 使用箭头函数或Function.bind。
说明:
箭头函数提供了更简洁的语法, 并且箭头函数中的this对象指向是不变的, this绑定到定义时所在的对象。 通常情况下, 这是我们想要的, 有很好的代码可读性, 而保存this对象的使用方式, 会让开发人员搞混。
2. 当你必须使用函数表达式(或传递一个匿名函数)时, 使用箭头函数。
说明:
箭头函数创造了一个新的this执行环境。 通常情况下, 能满足你的需求, 而且这样的写更为简洁。 如果你有一个相当复杂的函数, 那么可以把逻辑部分转移到一个函数声明上。
NG:
[1, 2, 3].map(function(x) {
return x * x;
});
Good:
[1, 2, 3].map( (x) => {
return x * x;
});
3. 如果一个函数适用一行写出并且只有一个参数, 那就把花括号、圆括号和return都省略掉, 如果不是, 那就不要省略。
[1, 2, 3].map( x => x * x;);
构造器
1. 采用class关键字定义类
2. 采用extends关键字实现继承。
说明:
因为extends是内建的继承方式, 并不会破坏instanceof原型检查。
解构
1. 使用解构存取和使用多属性对象。
说明:
ES6允许按照一定的模式, 从数组和对象中提取值、对变量进行赋值, 这称之为解构, 解构赋值避免了临时变量或对象, 给JavaScript书写带来了很大的便利性, 同时也提高了代码的可读性。
NG:
function getFullName (user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
Good:
function getFullName ({firstName, lastName}) {
return `${firstName} ${lastName}`;
}
2. 将数组成员赋值给变量时, 使用数组解析。
3. 需要回传多个值时, 使用对象解构, 而不是数组解构。
说明:
对象解构在增加属性或改变排序时, 无需改变调用时的位置。
String
1. 长度超过80的字符串应该使用字符串连接换行。
2. 构建字符串时, 使用字符串模板而不是字符串连接。
function sayHi(name) {
return `How are you, ${name}`;
}
3. 数组遍历采用for/of, 对象遍历采用for/in。
let arr = [1, 2, 3, 4];
let sum = 0;
for (let num of arr) {
sum += num;
}
存取器
1. 属性的存取函数不是必须的, 如果需要存储函数使用get方法和set方法。 如果属性是布尔值, 存取函数是isVal()或hasVal()。
NG:
dragon.age();
dragon.age(25);
if (!dragon.age()) {
return false;
}
Good:
dragon.getAge();
dragon.setAge(25);
if (!dragon.getAge()) {
return false;
}
2. 创建get()和set()函数要保持一致。
class Demo {
constructor (options = {}) {
const lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}
set (key, val) {
this[key] = val;
}
get (key) {
return this[key];
}
}