为什么做这件事

指标市面上有很多前端开发标准,有的过于成旧,有的过于简略、全面,好将来培优增长前端团队针对目前这些问题,整顿了一份最新最残缺的前端开发标准,包含JS、CSS、HTML、lint、Vue等。

做这件事的意义

  1. 进步代码的可读性和可维护性。
    有统计显示,在一个中大型项目中,代码的前期保护老本远高于开发成本。所以,进步代码的可维护性能极大减低我的项目的保护老本。
  2. 实现我的项目研发的标准化。
    目前的我的项目研发流程相似于汽车等工业产品的流水线生产模式,通过开发标准,能有利于研发的标准化。
  3. 缩小bug、利于代码审查。
    在艺术的世界里咱们提倡天马行空,然而,在代码的世界里,咱们要提倡开发标准,这样会缩小bug的数量和升高问题的排查工夫。

JS篇

1、代码格调

1.1、编码格局

JavaScript 文件应用无 BOM 的 UTF-8 编码。
ps: UTF-8 编码具备更宽泛的适应性。BOM 在应用程序或工具解决文件时可能造成不必要的烦扰。

1.2、代码缩进

应用 2 个空格缩进

1.3、代码空格

1.3.1、二元运算符两侧各有一个空格,一元运算符与操作对象之间不容许有空格
// badlet a=12a=b+ca ++// goodlet a = 14a = b + ca++
1.3.2、代码块起始的左花括号 { 前有一个空格。
// badif (condition){}while (condition){}function funcName(){}// goodif (condition) {}while (condition) {}function funcName() {}
1.3.3、if / else / for / while / function / switch / do / try / catch / finally 关键字后,有一个空格。
// badif(condition) {}while(condition) {}// goodif (condition) {}while (condition) {}
1.3.4、在对象创立时,属性中的 : 之后有一个空格,: 之前不容许有空格。
// badvar obj = {    a : 1,    b:2,    c :3}// goodvar obj = {    a: 1,    b: 2,    c: 3}

##### 1.3.5、函数申明、具名函数表达式、函数调用中,函数名和 ( 之间不容许有空格。

// badfunction funcName () {const func = function (){}funcName ()// goodfunction funcName() {}const funcName = function() {}funcName()

2、变量申明

2.1、const, let ,var

对所有变量尽量都应用const let ,尽量不要应用var。
ps:这样做能够确保你无奈重新分配援用,以避免出现谬误和难以了解的代码。
另外将所有的 const 和 let 分组 。 如果没有写关键字,变量就会裸露在全局上下文中,这样很可能会和现有变量抵触,另外,也很难明确该变量的作用域是什么。

// badvar a = 1// goodconst a = 1const b = 2let c = 3let d = 4

2.2、保留字

别应用保留字作为对象的键值,这样在 IE8 下不会运行

// badconst a = {  default: {},  // default 是保留字  common: {}}// goodconst a = {  defaults: {},  common: {}}

2.3、引号问题

对字符串应用单引号 ,尽量不应用双引号。
ps: 因为大多时候咱们的字符串。特地html会呈现双引号

// badconst a = "123"// goodconst a = '123'

2.4、分号问题

以下几种状况结尾可不带分号
申明变量时、import、export、return、throw、break
ps:不带分号简洁明了,并且依据ASI【Automatic Semicolon Insertion】机制,解析时会主动给插入分号

// badlet a = 12;import xxx from 'aa';return;throw new Error(err);break;// goodlet a = 12import xxx from 'aa'returnthrow new Error(err)break

2.5、链式赋值

变量不要进行链式赋值,变量链式赋值会创立暗藏的全局变量

// bad let a = b = 2// goodlet a = 2let b = 2

2.6、多余变量

不容许呈现未被应用的变量,申明但未被应用的变量通常是不齐全重构犯下的谬误,这种变量在代码里节约空间并会给读者造成困扰

3、创立变量

3.1、创建对象变量

请应用字面量值创立
ps: 代码量少,易读性高,运行速度快

// badconst a = new Object()const b = new Array()// goodconst a = {}const b = []

3.2、创立函数

不要应用Function构造函数创立函数
ps:代码量少,易读性高,运行速度快

// badconst add = new Function('a', 'b', 'return a + b')// goodconst func1 = function() {}

3.3、创立字符串变量

字符串太长的时候,倡议不要应用字符串连接符换行\,而是应用 +

// badconst string = '好将来\    是一家十分好的教育公司\    是真的十分好'// good    const str = '好将来' +  '是一家十分好的教育公司' +  '是真的十分好' 程序化生成字符串时,倡议应用模板字符串const test = 'test'// badconst str = 'a' + 'b' + test// goodconst 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、对象解构

当须要应用对象的多个属性时,请应用解构赋值

// badfunction getFullName(user) {  const firstName = user.firstName  const lastName = user.lastName  return `${firstName} ${lastName}`}// goodfunction getFullName({ firstName, lastName }) {  return `${firstName} ${lastName}`}

5.2、数组解构

当须要应用数组的多个值时,请同样应用解构赋值

const arr = [1, 2, 3, 4]// badconst first = arr[0]const second = arr[1]// goodconst [first, second] = arr

5.3、函数回传参数的解构

函数须要回传多个值时,请应用对象的解构,而不是数组的解构。
ps: 这样能够非破坏性地随时减少或者扭转属性程序

// badfunction doSomething() {  return [top, right, bottom, left]}// 如果是数组解构,那么在调用时就须要思考数据的程序const [top, xx, xxx, left] = doSomething()// goodfunction doSomething() {  return { top, right, bottom, left }}// 此时不须要思考数据的程序const { top, left } = doSomething()

5.4、解构的默认值

解构变量时减少默认值,避免读到空值或者undefined

// badconst { a, b } = { a: 3 }// goodconst { a = 10, b = 1 } = { a: 3 }

6、类&构造函数

6.1、应用 class,防止间接操作 prototype

ps:容易造成全局净化,造成抵触,定位bug不好定位。

// badfunction Queue(contents = []) {  this._queue = [..contents]}Queue.prototype.pop = function () {  const value = this._queue[0]  this._queue.splice(0, 1)  return value}// goodclass Queue {  constructor(contents = []) {    this._queue = [...contents]  }  pop() {    const value = this._queue[0]    this._queue.splice(0, 1)    return value  }}

6.2、应用 extends 来实现继承

ps长处:清晰,不便,并且这是一个不会毁坏 instanceof 的内建实现原型式继承的形式

// badconst inherits = require('inherits')function PeekableQueue(contents) {  Queue.apply(this, contents)}inherits(PeekableQueue, Queue)PeekableQueue.prototype.peek = function () {  return this.queue[0]}// goodclass PeekableQueue extends Queue {  peek () {    return this.queue[0]  }}

7、对象属性

7.1、优先应用 . 来拜访对象属性

ps: 益处是简洁,不便

const joke = {  name: 'haha',  age: 28}// badconst name = joke['name']// goodconst 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'// badif (name == 'test') {  // ...}// goodif (name === 'test') {  // ...}

8.2、尽可能应用简洁的表达式

const name = ''// badif (name === '') {    // ......}// goodif (!name) {    // ......}

8.3、如果函数或全局中的 else 块后没有任何语句,能够删除 else

// badfunction getName() {    if (name) {       return name;    } else {       return 'unnamed';    }}// goodfunction 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 = falseconst hasSelected = false

12、&& 和 ||

二元布尔操作符是可短路的, 只有在必要时才会计算到最初一项。

// a++并不会执行let x = falselet a = 1let 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  }}