目录
1、引用类型:
1.1、引用类型使用const,避免使用var。理由:这样能确保你不能对引用重新赋值,不会因此出现 bug 或难以理解的代码
// bad
var a = { name: 'zx', age: 24};
var b = [1, 2, 3];
// good
const a = { name: 'zx', age: 24};
const b = [1, 2, 3];
1.2、 如果必须对引用赋值,可以使用let代替var。理由:let是块级作用域,而var是函数作用域,函数作用域存在变量提升等问题,可能会覆盖父级变量,让代码难以理解。
// bad
var count = 1;
if (true) {
count += 1;
}
// good, use the let.
let count = 1;
if (true) {
count += 1;
}
2、对象类型:
2.1 、使用对象字面量创建对象而不是 new Object()。理由:1、它的代码量更少,更易读 。 2、不需要作用域解析,运行速度更快 。3、Object()构造函数可以接收参数,通过这个参数可以把对象实例的创建过程委托给另一个内置构造函数,并返回另外一个对象实例,而这往往不是你想要的。
// bad
const item = new Object();
// good
const item = {};
// 空对象
var o = new Object();
console.log(o.constructor === Object); // true
// 数值对象
var o = new Object(1);
console.log(o.constructor === Number); // true
console.log(o.toFixed(2)); // "1.00"
// 字符串对象
var o = new Object("I am a string");
console.log(o.constructor === String); // true
// 普通对象没有substring()方法,但字符串对象有
console.log(typeof o.substring); // "function"
// 布尔值对象
var o = new Object(true);
console.log(o.constructor === Boolean); // true
2.2、在创建具有动态属性名的对象时,使用计算属性名。理由:可以在一个地方定义所有属性,可读性更高
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.3、在对象声明开始的位置将您的简写属性分组。理由:这样更容看出哪些属性用了简写属性
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
episodeOne: 1,
twoJediWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJediWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
2.4、只有对无效的标识符的属性才使用引号。理由:1、有利于浏览器高亮显示,提高易读性。2、有利于js引擎的优化
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5,
};
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
};
2.5、不要直接调用Object.prototype的方法,比如 hasOwnProperty、propertyIsEnumerable、isPrototypeOf。理由:这些方法可能被调用对象的属性所屏蔽,调用对象也可能为null。
// bad
console.log(object.hasOwnProperty(key));
// good
console.log(Object.prototype.hasOwnProperty.call(object, key));
// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));
2.6、浅拷贝对象的时候使用 … 操作符而不是 Object.assign
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ
delete copy.a; // so does this
// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
// good
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
2.7、在访问和使用对象的多个属性时,使用对象的解构。理由:这样可以减少对对象属性的引用
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(user) {
const { firstName, lastName } = user;
return `${firstName} ${lastName}`;
}
3、数组
3.1 、使用拓展运算符 … 复制数组
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i += 1) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
3.2、数据项有多行的数组,在数据项的开头和结尾使用换行。
// bad
const arr = [
[0, 1], [2, 3], [4, 5],
];
const objectInArray = [{
id: 1,
}, {
id: 2,
}];
const numberInArray = [
1, 2,
];
// good
const arr = [[0, 1], [2, 3], [4, 5]];
const objectInArray = [
{
id: 1,
},
{
id: 2,
},
];
const numberInArray = [1,2,];
4、字符串
4.1、字符串使用单引号 ' '
// bad
const name = "Capt. Janeway";
// bad - 模板字面量应该包含插值或换行符
const name = `Capt. Janeway`;
// good
const name = 'Capt. Janeway';
4 .2、编程时避免使用字符串拼接,转而使用模版字符串
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
}
// bad
function sayHi(name) {
return ['How are you, ', name, '?'].join();
}
// bad
function sayHi(name) {
return `How are you, ${ name }?`;
}
// good
function sayHi(name) {
return `How are you, ${name}?`;
}
4.3、不要对字符串使用eval()方法
4.4、不要使用不必要的转译符号
// bad
const foo = '\'this\' \i\s \"quoted\"';
// good
const foo = '\'this\' is "quoted"';
const foo = `my name is '${name}'`;
5 、函数
5.1、不要使用arguments作为函数的参数,因为这会覆盖函数作用域内的 arguments 对象。
// bad
function foo(name, options, arguments) {
// ...
}
// good
function foo(name, options, args) {
// ...
}
5.2、使用 ... 语法替代 arguments。理由:... 语法能够得到一个纯数组,且能够明确你要传入的参数
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// good
function concatenateAll(...args) {
return args.join('');
}
5.3、使用函数的默认参数语法而不是改变函数的参数
// really bad
function handleThings(opts) {
// No! We shouldn’t mutate function arguments.
// Double bad: if opts is falsy it'll be set to an object which may
// be what you want but it can introduce subtle bugs.
opts = opts || {};
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
5.4、函数的默认参数要放到最后
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
5.5、永远不要改变函数的参数
// bad
function f1(obj) {
obj.key = 1;
}
// bad
function f1(a) {
a = 1;
// ...
}
5.6、必须是用来匿名函数时,使用箭头函数。理由:箭头函数里的 this 指向的上下文更多时候是你想要的
6 、类
6.1、使用class ,而不要直接使用 prototype。因为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;
}
}
6.2、使用 extends 继承。理由:这是一个内置的方法,并且不会破坏instanceof
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
return this.queue[0];
};
// good
class PeekableQueue extends Queue {
peek() {
return this.queue[0];
}
}
6.3、 方法中可以返回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);