导航
JavaScript 是一种客户端脚本语言,这里列出了编写 JavaScript 时需要遵守的规则。
原始类型: 存取原始类型直接作用于值本身
布尔类型
Null 类型
Undefined 类型
数字类型
BigInt 类型
字符串类型
符号类型 Symbol
const foo = 1;
let bar = foo;
bar = 9;
console.log(foo, bar); // 1, 9
复杂类型: 访问复杂类型作用于值的引用
object
array
Function
const foo = [1, 2, 3];
const bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // 9, 9
const 和 let 都是块级作用域,var 是函数级作用域{
let a = 1;
const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
const,不要使用 var,eslint: prefer-const, no-const-assign原因:这样做可以确保你无法重新分配引用,以避免出现错误和难以理解的代码
// bad
var a = 1;
var b = 2;
// good
const a = 1;
const b = 2;
let 代替 var,eslint: no-var原因:
let是块级作用域的,而不像var属于函数级作用域
// bad
var count = 1;
if (count < 10) {
count += 1;
}
// good
let count = 1;
if (count < 10) {
count += 1;
}
// bad
const a = new Object{};
// good
const a = {};
// bad
const a = {
default: {}, // default 是保留字
common: {}
};
// good
const a = {
defaults: {},
common: {}
};
原因:因为这样做就可以让你在一个地方定义所有的对象属性
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
};
// bad
const item = {
value: 1,
addValue: function (val) {
return item.value + val;
}
};
// good
const item = {
value: 1,
addValue (val) {
return item.value + val;
}
};
原因:这样更简短且描述更清楚
const job = 'FrontEnd';
// bad
const item = {
job: job
};
// good
const item = {
job
};
原因:这样更容易区分哪些属性用了简写的方式
const job = 'FrontEnd';
const department = 'One';
// bad
const item = {
sex: 'male',
job,
age: 25,
department
};
// good
const item = {
job,
department,
sex: 'male',
age: 25
};
原因:因为通常来说我们认为这样主观上会更容易阅读,这样会带来代码高亮上的提升,同时也更容易被主流 JS 引擎优化
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5
};
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5
};
Object.prototype 的方法, 例如 hasOwnProperty, propertyIsEnumerable 和 isPrototypeOf 方法,eslint: no-prototype-builtins原因:这些方法可能会被对象自身的同名属性覆盖 - 比如
{ hasOwnProperty: false }或者对象可能是一个null对象(Object.create(null))
// bad
console.log(object.hasOwnProperty(key));
// good
console.log(Object.prototype.hasOwnProperty.call(object, key));
// best
const has = Object.prototype.hasOwnProperty; // 缓存一次查找,在模块作用域内
console.log(has.call(object, key));
... 来做对象浅拷贝而不是使用 Object.assign,使用对象剩余操作符来获得一个包含确定的剩余属性的新对象// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // 这会改变`original` ಠ_ಠ
delete copy.a; // original G 了
// 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 }
// bad
const items = new Array();
// good
const items = [];
push 方法const items = [];
// bad
items[items.length] = 'test';
// good
items.push('test');
... 复制数组// bad
const items = [];
const itemsCopy = [];
const len = items.length;
let i;
// bad
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
itemsCopy = [...items];
... 而不是 Array.fromconst foo = document.querySelectorAll('.foo');
// good
const nodes = Array.from(foo);
// best
const nodes = [...foo];
Array.from 来将一个类数组对象转换为数组const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
// bad
const arr = Array.prototype.slice.call(arrLike);
// good
const arr = Array.from(arrLike);
Array.from 代替扩展运算符 ..., 因为这可以避免创建中间数组// bad
const baz = [...foo].map(bar);
// good
const baz = Array.from(foo, bar);
map 等方法时,请使用 return 声明,如果是单一声明语句的情况,可省略 return// good
[1, 2, 3].map(x => {
const y = x + 1;
return x * y;
})
// good
[1, 2, 3].map(x => x + 1);
// bad
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatten = memo.concat(item);
flat[index] = flatten;
})
// good
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatten = memo.concat(item);
flat[index] = flatten;
return flatten;
})
// bad
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
} else {
return false;
}
})
// good
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
}
return false;
})
// 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
];
愿意:解构可以避免创建属性的临时引用
// 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}`;
}
// better
function getFullName ({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
原因:可以非破坏性地随时增加或者改变属性顺序
// bad
function doSomething () {
return [top, right, bottom, left];
}
// 如果是数组解构,那么在调用时就需要考虑数据的顺序
const [top, xx, xxx, left] = doSomething();
// good
function doSomething () {
return { top, right, bottom, left };
}
// 此时不需要考虑数据的顺序
const { top, left } = doSomething();
'',eslint: quotes// bad
const department = "One";
// good
const department = 'One';
\\,而是使用 +const str = '前端开发规范 前端开发规范 前端开发规范' +
'前端开发规范 前端开发规范' +
'前端开发规范';
const test = 'test';
// bad
const str = ['a', 'b', test].join();
// bad
const str = 'a' + 'b' + test;
// good
const str = `ab${test}`;
// bad
const foo = '\\'this\\' \\i\\s \\"quoted\\"';
// good
const foo = '\\'this\\' is "quoted"';
const foo = `my name is '${name}'`;