javascript 代码规范
- 命名全部采用驼峰命名(camelCase)。
- 非打包项目中尽量减少使用 es6~10 的新语法,使用前先看浏览器兼容性(caniuse)。
- 打包项目尽可能使用 es6~10 的新语法。
- ECMAScript 6 入门
- 语法规范,除了下面列出的(列出的也有的是重点的),其余的尽量参考上述链接内容。
对象
请使用对象方法的简写方式
// bad const item = { value: 1, addValue: function (val) { return item.value + val } } // good const item = { value: 1, addValue(val) { return item.value + val } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17请使用对象属性值的简写方式
const job = 'FrontEnd' // bad const item = { job: job } // good const item = { job }
1
2
3
4
5
6
7
8
9
10
11
数组
一维数组使用拓展运算符
...
复制数组// 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]
1
2
3
4
5
6
7
8
9
10
11
12
13使用数组的
map/reduce/filter
等方法时,请使用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 })
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
35
36
37
38
39
40
41
42
43
解构赋值
当需要使用对象的多个属性时,请使用解构赋值
// 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}` }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19当需要使用数组的多个值时,请同样使用解构赋值
const arr = [1, 2, 3, 4] // bad const first = arr[0] const second = arr[1] // good const [first, second] = arr
1
2
3
4
5
6
7
8函数需要回传多个值时,请使用对象的解构,而不是数组的解构
// 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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
字符串
程序化生成字符串时,请使用模板字符串
const test = 'test' // bad const str = ['a', 'b', test].join() // bad const str = 'a' + 'b' + test // good const str = `ab${test}`
1
2
3
4
5
6
7
8
9
10
函数
不要使用
arguments
,可以选择使用...
arguments
只是一个类数组,而...
是一个真正的数组// bad function test () { const args = Array.prototype.slice.call(arguments) return args.join('') } // good function test (...args) { return args.join('') }
1
2
3
4
5
6
7
8
9
10不要更改函数参数的值,或者说使用函数参数的默认值
// bad function test (opts) { opts = opts || {} } // good function test (opts = {}) { // ... }
1
2
3
4
5
6
7
8
9
原型
使用
class
,避免直接操作prototype
// 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 } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
模块
使用标准的 ES6 模块语法
import
和export
// bad const util = require('./util') module.exports = util // good import Util from './util' export default Util // better import { Util } from './util' export { Util }
1
2
3
4
5
6
7
8
9
10
11不要使用
import
的通配符*
,这样可以确保你只有一个默认的export
// bad import * as Util from './util' // good import Util from './util'
1
2
3
4
5
迭代器
不要使用
iterators
const numbers = [1, 2, 3, 4, 5] // bad let sum = 0 for (let num of numbers) { sum += num } // good let sum = 0 numbers.forEach(num => sum += num) // better const sum = numbers.reduce((total, num) => total + num, 0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
对象属性
除非属性是变量,否则一律使用
.
来访问对象属性const joke = { name: 'haha', age: 28 } // bad const name = joke['name'] // good const name = joke.name
1
2
3
4
5
6
7
8
9
10
变量声明
声明变量时,请使用
const
、let
关键字,如果没有写关键字,变量就会暴露在全局上下文中,这样很可能会和现有变量冲突,另外,也很难明确该变量的作用域是什么。这里推荐使用const
来声明变量,我们需要避免全局命名空间的污染。// bad demo = new Demo() // good const demo = new Demo()
1
2
3
4
5将所有的
const
和let
分组,次点仅是为了查看代码顺眼。// bad let a const b let c const d let e // good const b const d let a let c let e
1
2
3
4
5
6
7
8
9
10
11
12
13
Hoisting
var
存在变量提升的情况,即var
声明会被提升至该作用域的顶部,但是他们的赋值并不会。而const
和let
并不存在这种情况,并且存在暂时性死区function example () { console.log(notDefined) // => throws a ReferenceError } function example () { console.log(declareButNotAssigned) // => undefined var declaredButNotAssigned = true } function example () { let declaredButNotAssigned console.log(declaredButNotAssigned) // => undefined declaredButNotAssigned = true } function example () { console.log(declaredButNotAssigned) // => throws a ReferenceError console.log(typeof declaredButNotAssigned) // => throws a ReferenceError const declaredButNotAssigned = true }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
函数说明
函数说明包含内容:
/**
* 函数说明,主要是用于实现什么功能
* @param {字段类型} 变量名 变量说明
* @return {返回值类型} 返回值说明
*/
2
3
4
5
比如:
/**
* 由一个组件,向上找到最近的指定组件
* @param {Object} context 当前上下文,比如你要基于哪个组件来向上寻找,一般都是基于当前的组件,也就是传入 this
* @param {String} componentName 要找的组件的 name
*/
function findComponentUpward(context, componentName) {
let parent = context.$parent;
let name = parent.$options.name;
while (parent && (!name || [componentName].indexOf(name) < 0)) {
parent = parent.$parent;
if (parent) name = parent.$options.name;
}
return parent;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
风格统一
使用 vue cli 创建项目的时候, linter 选择 ESLint + Standard config 。
Standard标准,它是一些前端工程师自定的标准。JavaScript Standard Style
代码规范 。