为什么做这件事
指标市面上有很多前端开发标准,有的过于成旧,有的过于简略、全面,好将来培优增长前端团队针对目前这些问题,整顿了一份最新最残缺的前端开发标准,包含 JS、CSS、HTML、lint、Vue 等。
做这件事的意义
- 进步代码的可读性和可维护性。
有统计显示,在一个中大型项目中,代码的前期保护老本远高于开发成本。所以,进步代码的可维护性能极大减低我的项目的保护老本。 - 实现我的项目研发的标准化。
目前的我的项目研发流程相似于汽车等工业产品的流水线生产模式,通过开发标准,能有利于研发的标准化。 - 缩小 bug、利于代码审查。
在艺术的世界里咱们提倡天马行空,然而,在代码的世界里,咱们要提倡开发标准,这样会缩小 bug 的数量和升高问题的排查工夫。
JS 篇
1、代码格调
1.1、编码格局
JavaScript 文件应用无 BOM 的 UTF-8 编码。
ps: UTF-8 编码具备更宽泛的适应性。BOM 在应用程序或工具解决文件时可能造成不必要的烦扰。
1.2、代码缩进
应用 2 个空格缩进
1.3、代码空格
1.3.1、二元运算符两侧各有一个空格,一元运算符与操作对象之间不容许有空格
// bad
let a=12
a=b+c
a ++
// good
let a = 14
a = b + c
a++
1.3.2、代码块起始的左花括号 {前有一个空格。
// bad
if (condition){
}
while (condition){
}
function funcName(){}
// good
if (condition) {
}
while (condition) {
}
function funcName() {}
1.3.3、if / else / for / while / function / switch / do / try / catch / finally 关键字后,有一个空格。
// bad
if(condition) {
}
while(condition) {
}
// good
if (condition) {
}
while (condition) {}
1.3.4、在对象创立时,属性中的 : 之后有一个空格,: 之前不容许有空格。
// bad
var obj = {
a : 1,
b:2,
c :3
}
// good
var obj = {
a: 1,
b: 2,
c: 3
}
##### 1.3.5、函数申明、具名函数表达式、函数调用中,函数名和 (之间不容许有空格。
// bad
function funcName () {const func = function (){}
funcName ()
// good
function funcName() {}
const funcName = function() {}
funcName()
2、变量申明
2.1、const, let ,var
对所有变量尽量都应用 const let,尽量不要应用 var。
ps:这样做能够确保你无奈重新分配援用,以避免出现谬误和难以了解的代码。
另外将所有的 const 和 let 分组。如果没有写关键字,变量就会裸露在全局上下文中,这样很可能会和现有变量抵触,另外,也很难明确该变量的作用域是什么。
// bad
var a = 1
// good
const a = 1
const b = 2
let c = 3
let d = 4
2.2、保留字
别应用保留字作为对象的键值,这样在 IE8 下不会运行
// bad
const a = {default: {}, // default 是保留字
common: {}}
// good
const a = {defaults: {},
common: {}}
2.3、引号问题
对字符串应用单引号,尽量不应用双引号。
ps: 因为大多时候咱们的字符串。特地 html 会呈现双引号
// bad
const a = "123"
// good
const a = '123'
2.4、分号问题
以下几种状况结尾可不带分号
申明变量时、import、export、return、throw、break
ps:不带分号简洁明了,并且依据 ASI【Automatic Semicolon Insertion】机制,解析时会主动给插入分号
// bad
let a = 12;
import xxx from 'aa';
return;
throw new Error(err);
break;
// good
let a = 12
import xxx from 'aa'
return
throw new Error(err)
break
2.5、链式赋值
变量不要进行链式赋值,变量链式赋值会创立暗藏的全局变量
// bad
let a = b = 2
// good
let a = 2
let b = 2
2.6、多余变量
不容许呈现未被应用的变量,申明但未被应用的变量通常是不齐全重构犯下的谬误,这种变量在代码里节约空间并会给读者造成困扰
3、创立变量
3.1、创建对象变量
请应用字面量值创立
ps: 代码量少,易读性高,运行速度快
// bad
const a = new Object()
const b = new Array()
// good
const a = {}
const b = []
3.2、创立函数
不要应用 Function 构造函数创立函数
ps:代码量少,易读性高,运行速度快
// bad
const add = new Function('a', 'b', 'return a + b')
// good
const func1 = function() {}
3.3、创立字符串变量
字符串太长的时候,倡议不要应用字符串连接符换行 \,而是应用 +
// bad
const string = ' 好将来 \
是一家十分好的教育公司 \
是真的十分好 '
// good
const str = '好将来' +
'是一家十分好的教育公司' +
'是真的十分好'
程序化生成字符串时,倡议应用模板字符串
const test = 'test'
// bad
const str = 'a' + 'b' + test
// good
const str = `ab${test}`
4、箭头函数
4.1、当你必须应用函数表达式(比方传递匿名函数)时,应用箭头函数标记
ps:它将创立在 this 上下文中执行的函数版本,通常是您想要的,并且语法更简洁
// bad
[1, 2, 3].map(function(x) {
const y = x + 1
return x * y
})
// good
[1, 2, 3].map(x => {
const y = x + 1
return x * y
})
4.2、箭头函数中参数的括号问题
箭头函数如果是只有一个参数时不加括号,简介明了
// bad
[1,2,3].map((x) => {
const y = x + 1
return x * y
})
// good
[1,2,3].map(x => {
const y = x + 1
return x * y
})
4.3、如果函数体只蕴含一条没有副作用的返回表达式的语句,能够省略花括号并应用隐式的 return,否则保留花括号并应用 return 语句
// bad
[1, 2, 3].map(number => {
const nextNumber = number + 1
`A string containing the ${nextNumber}`
})
// good
[1, 2, 3].map(number => `A string containing the ${number}`)
5、解构赋值
ps:解构能够防止创立属性的长期援用
5.1、对象解构
当须要应用对象的多个属性时,请应用解构赋值
// bad
function getFullName(user) {
const firstName = user.firstName
const lastName = user.lastName
return `${firstName} ${lastName}`
}
// good
function getFullName({firstName, lastName}) {return `${firstName} ${lastName}`
}
5.2、数组解构
当须要应用数组的多个值时,请同样应用解构赋值
const arr = [1, 2, 3, 4]
// bad
const first = arr[0]
const second = arr[1]
// good
const [first, second] = arr
5.3、函数回传参数的解构
函数须要回传多个值时,请应用对象的解构,而不是数组的解构。
ps: 这样能够非破坏性地随时减少或者扭转属性程序
// 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()
5.4、解构的默认值
解构变量时减少默认值,避免读到空值或者 undefined
// bad
const {a, b} = {a: 3}
// good
const {a = 10, b = 1} = {a: 3}
6、类 & 构造函数
6.1、应用 class,防止间接操作 prototype
ps:容易造成全局净化,造成抵触,定位 bug 不好定位。
// 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 来实现继承
ps 长处:清晰,不便,并且这是一个不会毁坏 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]
}
}
7、对象属性
7.1、优先应用 . 来拜访对象属性
ps: 益处是简洁,不便
const joke = {
name: 'haha',
age: 28
}
// bad
const name = joke['name']
// good
const name = joke.name
7.2、当拜访的属性是变量或者数字时只能应用 []
const luke = {
jedi: true,
age: 28,
12: 'num'
}
function getProp(prop) {return luke[prop]
}
const isJedi = getProp('jedi')
8、条件运算
8.1、应用 === 和 !== 而非 == 和 !=
const name = 'test'
// bad
if (name == 'test') {// ...}
// good
if (name === 'test') {// ...}
8.2、尽可能应用简洁的表达式
const name = ''
// bad
if (name === '') {// ......}
// good
if (!name) {// ......}
8.3、如果函数或全局中的 else 块后没有任何语句,能够删除 else
// bad
function getName() {if (name) {return name;} else {return 'unnamed';}
}
// good
function getName() {if (name) {return name;}
return 'unnamed';
}
9、eval()
eval 办法比拟 evil,所以咱们约定禁止应用该办法
ps: eval 会引起 xss 攻打;eval 会烦扰作用域链等等,不举荐在代码中应用 eval
10、不要批改内置对象的原型
11、变量命名规定
11.1、惯例变量用小驼峰格局
let userInfo = {}
11.2、全局常量用大写字母,多个字母以下划线连贯
const MATH_PI = 3.14
11.3、类内的公有变量以下划线结尾
11.4、类名以大驼峰格局
class UserInfo {}
11.5、一般函数名用小驼峰格局
function getUserInfo() {}
11.6、枚举变量用大驼峰格局,枚举属性 应用全副字母大写,单词间下划线分隔
const Week = {
MONDAY: 0,
TUESDAY: 1
}
11.7、boolean 类型的变量倡议应用 is 或 has 结尾【倡议】
// 惯例变量
const loginStatus = 0
// 全局常量
const COUNT = 0
// 全局常量
const MAX_NUM = 99
// 类的申明
class Point {constructor(name, age) {
this._name = name
this._age = age
}
toString() {return '(' + this._name + ',' + this._age + ')'
}
}
// 一般函数
function stringFormat(source) {
}
// 枚举变量
const TargetState = {
READING: 1,
READED: 2,
APPLIED: 3
}
// boolean 类型的变量
const isReady = false
const hasSelected = false
12、&& 和 ||
二元布尔操作符是可短路的, 只有在必要时才会计算到最初一项。
// a++ 并不会执行
let x = false
let a = 1
let y = x && a++
13、正文标准
13.1、单行正文
独占一行,// 后跟一个空格,缩进与下一行被正文阐明的代码统一。
13.2、多行正文
尽量避免应用 /*…/ 这样的多行正文。有多行正文内容时,应用多个单行正文。
13.3、文档化正文格局
应用 @key desc 格局来书写
罕用的关键词有:
@author 作者
@param 参数
@example 示例
@link 链接
@namespace 命名空间
@requires 依赖模块
@return 返回值
@version 版本号
正文的 param 的类型定义 都是以{开始, 以} 完结
罕用的 param 的类型:{String}, {Number}, {Boolean}, {Object}, {Function}, {RegExp}, {Array}, {Date}
13.4、函数 / 办法的正文
蕴含函数的阐明,有参数和返回值时必须用正文标识
/**
* @desc 函数形容
* @param {String} p1 参数 1 的阐明
* @param {String} p2 参数 2 的阐明
* @param {Number=} p3 参数 3 的阐明(可选)* @return {Object} 返回值形容
*/
function foo(p1, p2, p3) {
return {
p1: p1,
p2: p2,
p3: p3
}
}