划词标注编辑器开发之旅

前端代码规范

  • 使用字面语法来创建对象。
1
2
3
4
5
// bad
const item = new Object();

// good
const item = {};
  • 在对象声明的时候将简写的属性进行分组。

为什么? 这样更容易的判断哪些属性使用的简写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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,
};
  • 尽量使用对象扩展操作符,而不是用 Object.assign 浅拷贝一个对象。 使用对象的 rest 操作符来获得一个具有某些属性的新对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // 变异的 `original` ಠ_ಠ
delete copy.a; // 这....

// 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 }
  • 如果数组有多行,则在开始的时候换行,然后在结束的时候换行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 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,
];
  • 对于多个返回值使用对象解构,而不是数组解构。

为什么? 你可以随时添加新的属性或者改变属性的顺序,而不用修改调用方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// bad
function processInput(input) {
// 处理代码...
return [left, right, top, bottom];
}

// 调用者需要考虑返回数据的顺序。
const [left, __, top] = processInput(input);

// good
function processInput(input) {
// 处理代码...
return { left, right, top, bottom };
}

// 调用者只选择他们需要的数据。
const { left, top } = processInput(input);
  • 使用默认的参数语法,而不是改变函数参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// really bad
function handleThings(opts) {
opts = opts || {};
// ...
}

// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}

// good
function handleThings(opts = {}) {
// ...
}
  • 总是把默认参数放在最后。
1
2
3
4
5
6
7
8
9
// bad
function handleThings(opts = {}, name) {
// ...
}

// good
function handleThings(name, opts = {}) {
// ...
}
  • 尽量使用 class. 避免直接操作 prototype .

为什么? class 语法更简洁,更容易推理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 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;
}
}
  • 不要使用迭代器。 应该使用 JavaScript 的高阶函数代替 for-in 或者 for-of

拥有返回值得纯函数比这个更容易解释。
使用 map() / every() / filter() / find() / findIndex() / reduce() / some() / … 遍历数组, 和使用 Object.keys() / Object.values() / Object.entries() 迭代你的对象生成数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const numbers = [1, 2, 3, 4, 5];

// bad
let sum = 0;
for (let num of numbers) {
sum += num;
}
sum === 15;

// good
let sum = 0;
numbers.forEach((num) => {
sum += num;
});
sum === 15;

// best (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;

// bad
const increasedByOne = [];
for (let i = 0; i < numbers.length; i++) {
increasedByOne.push(numbers[i] + 1);
}

// good
const increasedByOne = [];
numbers.forEach((num) => {
increasedByOne.push(num + 1);
});

// best (keeping it functional)
const increasedByOne = numbers.map(num => num + 1);
  • 把 const 声明的放在一起,把 let 声明的放在一起。

为什么? 这在后边如果需要根据前边的赋值变量指定一个变量时很有用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// bad
let i, len, dragonball,
items = getItems(),
goSportsTeam = true;

// bad
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;

// good
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;
  • 使用定义变量的时候把它们放在一个合理的地方。

    let 和 const 是块级作用域而不是函数作用域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// bad - 不必要的函数调用
function checkName(hasName) {
const name = getName();

if (hasName === 'test') {
return false;
}

if (name === 'test') {
this.setName('');
return false;
}

return name;
}

// good
function checkName(hasName) {
if (hasName === 'test') {
return false;
}

const name = getName();

if (name === 'test') {
this.setName('');
return false;
}

return name;
}
作者: 张熠
文章链接: https://crazyoctopusdan.github.io/2019/07/10/%E5%89%8D%E7%AB%AF%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.