1.创建有动态属性名的对象时,使用可被计算的属性名称。
这样可以让你在一个地方定义所有的对象属性。
function getKey(k) {
return `a key named ${k}`;
}
// bad
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true;
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
2.使用对象属性值和方法的简写
达到更简短更具描述性的作用
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
lukeSkywalker: lukeSkywalker,
addValue: function (value) {
return atom.value + value;
},
};
// good
const obj = {
lukeSkywalker,
addValue(value) {
return atom.value + value;
},
};
3.在对象属性声明前把简写的属性分组
这样能清楚地看出哪些属性使用了简写。
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
episodeOne: 1,
twoJedisWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJedisWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
4.只使用引号标注无效标识符的属性
好的编码习惯
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5,
};
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
};
5.使用数组展开方法…来拷贝数组
好的编码习惯
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (let i = 0; i < len; i += 1) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
6. 在访问和使用对象的多个属性的时候使用对象的解构
解构可以避免为这些属性创建临时引用
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(obj) {
const { firstName, lastName } = obj;
return `${firstName} ${lastName}`;
}
// best
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
7.对于多个返回值使用对象解构,而不是数组解构
可以随时添加新的属性或者改变属性的顺序,而不用修改调用方
// bad
function processInput(input) {
// then a miracle occurs
return [left, right, top, bottom];
}
// 调用时需要考虑回调数据的顺序。
const [left, __, top] = processInput(input);
// good
function processInput(input) {
// then a miracle occurs
return { left, right, top, bottom };
}
// 调用时只选择需要的数据
const { left, right } = processInput(input);
8.使用默认的参数语法,而不是改变函数参数
编码习惯
// really bad
function handleThings(opts) {
// 不!我们不应该改变函数参数。
// 更加糟糕: 如果参数 opts 是 false 的话,它就会被设定为一个对象。
// 但这样的写法会造成一些 Bugs。
//(译注:例如当 opts 被赋值为空字符串,opts 仍然会被下一行代码设定为一个空对象。)
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
9.Generator 函数是 ES6 提供的一种异步编程解决方案.
为什么需要Generator?为了解决javascript异步回调层层嵌套的问题,Generator 函数提供了异步编程解决方案。他有以下几个特征:
• function关键字后面会带一个*号;函数体内部会使用yield表达式
• Generator函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
const hw = helloWorldGenerator();
hw.next();
// { value: 'hello', done: false }
hw.next();
// { value: 'world', done: false }
hw.next();
// { value: 'ending', done: true }
hw.next();
// { value: undefined, done: true }
10.总是使用 class。避免直接操作 prototype
class 语法更为简洁更易读。ES6的类class只是一个语法糖,完全可以看作构造函数的另一种写法。新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法。
// bad
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// good
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
11.方法可以返回 this 来供其内部方法调用
编码习惯
// bad
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined
// good
class Jedi {
jump() {
this.jumping = true;
return this;
}
setHeight(height) {
this.height = height;
return this;
}
}
const luke = new Jedi();
luke.jump()
.setHeight(20);
12.建议使用扩展运算符而非.apply()
编码习惯
// bad
foo.apply(undefined, args);
foo.apply(null, args);
obj.foo.apply(obj, args);
// good
foo(...args);
obj.foo(...args);