团队JS规范

版本号 作者 时间 版本 内容摘要
v1.0 eleven 2018-05-16 1.0.0 文档初始化

JS规范

1. 类型

简单类型:

  • 字符串
  • 数值
  • 布尔类型
  • null
  • undefined
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

2. 引用

const 和 let 都是块级作用域,var 是函数级作用域

  • 对所有引用都使用 const,不要使用 var
    推荐
const a = 1
const b = 2

不推荐

var a = 1
var b = 2
  • 如果引用是可变动的,则使用 let
    推荐
let count = 1
if (count < 10) {
  count += 1
}

不推荐

var count = 1
if (count < 10) {
  count += 1
}

3.对象

请使用字面量值创建对象

// bad
const a = new Object{}
// good
const a = {}

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

// bad
const a = {
  default: {},  // default 是保留字
  common: {}
}
// good
const a = {
  defaults: {},
  common: {}
}

请使用对象方法的简写方式

// 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 = 'FS'
// bad
const item = {
  sex: 'male',
  job,
  age: 25,
  department
}
// good
const item = {
  job,
  department,
  sex: 'male',
  age: 25
}

4.数组

请使用字面量值创建数组

// bad
const items = new Array()
// good
const items = []

向数组中添加元素时,请使用 push 方法

const items = []
// bad
items[items.length] = 'test'
// good
items.push('test')

向数组中添加元素时,请使用 push 方法

// 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]

使用数组的 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
})

5. 解构赋值

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

// 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()

6.字符串

字符串统一使用单引号的形式 ' '

// bad
const department = "FS"
// good
const department = 'FS'

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

const str = '凹凸实验室 凹凸实验室 凹凸实验室' +
  '凹凸实验室 凹凸实验室 凹凸实验室' +
  '凹凸实验室 凹凸实验室'

程序化生成字符串时,请使用模板字符串

const test = 'test'
// bad
const str = ['a', 'b', test].join()
// bad
const str = 'a' + 'b' + test
// good
const str = `ab${test}`

7.函数

请使用函数声明,而不是函数表达式

// bad
const foo = function () {
  // do something
}
// good
function foo () {
  // do something
}

不要在非函数代码块中声明函数

// bad
if (isUse) {
  function test () {
    // do something
  }
}
// good
let test
if (isUse) {
  test = () => {
    // do something
  }
}

不要使用 arguments,可以选择使用 ...

// bad
function test () {
  const args = Array.prototype.slice.call(arguments)
  return args.join('')
}
// good
function test (...args) {
  return args.join('')
}

不要更改函数参数的值

// bad
function test (opts) {
  opts = opts || {}
}
// good
function test (opts = {}) {
  // ...
}

8.分号

我们遵循 Standard 的规范,不使用分号。

// bad
const test = 'good';
(function () {
  const str = 'hahaha';
})()
// good
const test = 'good'
;(() => {
  const str = 'hahaha'
})();

9.大括号风格

在编程过程中,大括号风格与缩进风格紧密联系,用来描述大括号相对代码块位置的方法有很多。
推荐

if (foo) {
  bar()
} else {
  baz()
}

10.变量命名

团队约定使用驼峰式命名

11.逗号空格

逗号前后的空格可以提高代码的可读性,团队约定在逗号后面使用空格,逗号前面不加空格。

推荐

var foo = 1, bar = 2

不推荐

var foo = 1,bar = 2
var foo = 1 , bar = 2
var foo = 1 ,bar = 2

12.变量声明

JavaScript 允许在一个声明中,声明多个变量。团队约定在声明变量时,一个声明只能有一个变量
推荐

var a
var b
var c

不推荐

var a, b, c

13.函数声明的空格

团队约定函数括号要加空格
推荐

function func (x) {
  // ...
}

不推荐

function func(x) {
  // ...
}

14.操作符的空格

团队约定操作符前后都需要添加空格
推荐

var sum = 1 + 2

不推荐

var sum = 1+2

15.三元条件判断(if 的快捷方法)

推荐

var sum = a=== 10 ? true : false;

不推荐

var sum;
if(a === 10){
    sum = true;
} else {
    sum = false
}

16.Js遍历数组的方式及其性能对比

Js数组遍历,基本有for、优化后的for、forin、forEach、while、forin、map、filter等一些方法,下面进行对比分析:

/**
     * for 循环
     * */
    let arr = [];
    let max = 10000000;
    setTimeout(function () {
        //初始化arr
        for (let i = 0; i < max; i++) {
            arr[i] = i + 1;
        }
    }, 1);

    /**
     * 检测简单的for循环
     * */
    function testDefaultFor(){
        let startTime, endTime, sum = 0;
        startTime = new Date();
        for(let i = 0; i < arr.length; i++){
            sum += arr[i];
        }
        endTime = new Date();
        console.log('普通for循环所需要时间:' + (endTime - startTime));
    }

    /**
     * 检测优化后的for循环
     * */
    function testDefaultFor2(){
        let startTime, endTime, sum = 0;
        startTime = new Date();
        for(let i = 0, len =  arr.length; i < len; i++){
            sum += arr[i];
        }
        endTime = new Date();
        console.log('普通for循环所需要时间:' + (endTime - startTime));
    }

    /**
     * 检测forEach循环所需时间
     * */
    function testDefaultForeach(){
        let startTime, endTime, sum = 0;
        startTime = new Date();
        arr.forEach(function(d, i){
            sum += d;
        })
        endTime = new Date();
        console.log('foreach循环所需要时间:' + (endTime - startTime));
    }

    /**
     * 检测while循环所需时间
     * */
    function testDefaultWhile(){
        let startTime, endTime, sum = 0, i = 0;
        startTime = new Date();
        while (i < max){
            sum += arr[i]*1;
            i++;
        }
        endTime = new Date();
        console.log('while循环所需要时间:' + (endTime - startTime));
    }

    /**
     * 检测while循环所需时间
     * */
    function testDefaultForIn(){
        let startTime, endTime, sum = 0;
        startTime = new Date();
        for(let i in arr){
            sum += i*1;
        }
        endTime = new Date();
        console.log('forin循环所需要时间:' + (endTime - startTime));
    }

    /**
     * 检测map循环所需时间
     * */
    function testDefaultMap(){
        let startTime, endTime, sum = 0;
        startTime = new Date();
        arr.map(function(d){
            sum += d*1;
        });
        endTime = new Date();
        console.log('map循环所需要时间:' + (endTime - startTime));
    }

    /**
     * 检测filter循环所需时间
     * */
    function testDefaultFilter(){
        let startTime, endTime, sum = 0;
        startTime = new Date();
        arr.filter(function(d){
            sum += d*1;
        });
        endTime = new Date();
        console.log('filter循环所需要时间:' + (endTime - startTime));
    }

最终得到的结果是:

  • 普通for循环所需要时间:99
  • 普通for循环所需要时间:76
  • foreach循环所需要时间:431
  • while循环所需要时间:81
  • forin循环所需要时间:1317
  • map循环所需要时间:1513
  • filter循环所需要时间:493
  • <font color="#f00">综合而言,forin与map最慢,优化后的for循环最快。</font>

17.总是使用带类型的判断符比较判断

总是使用 === 精确的比较操作符,而不是==,避免在判断的过程中,由 JavaScript 的强制类型转换所造成的困扰。

18.变量赋值时的逻辑操作

逻辑操作符 || 和 && 也可被用来返回布尔值。如果操作对象为非布尔对象,那每个表达式将会被自左向右地做真假判断。基于此操作,最终总有一个表达式被返回回来。这在变量赋值时,是可以用来简化你的代码的。
推荐

x = x || y || 1

不推荐

if(!x){
    if(!y){
        x = 1
    } else {
        x = y
    }
}

19.代码注释规范

注释是你自己与你的小伙伴们了解代码写法和目的的唯一途径。特别是在写一些看似琐碎的无关紧要的代码时,由于记忆点不深刻,注释就变得尤为重要了。

函数注释:
推荐

/**
* 测试的fun函数
* @param id 某个订单的订单id
* @param type 订单类型 0:未支付;1:支付成功;2:支付中;3:支付失败;
* @param callback 回调函数
* @returns {Promise.<TRsult>}
*/
function testFun(id, type, callback){
    ..........
}

单行注释:
推荐

var test = '你好'; // 测试的字段注释

20.使用严格模式

use strict;
........

为什么使用严格模式:

消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。
"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。

另一方面,同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。掌握这些内容,有助于更细致深入地理解Javascript,让你变成一个更好的程序员。

21.禁用eval()

由于 eval 方法比较 evil,所以我们约定禁止使用该方法

22.禁用with()

由于 with 方法会产生神奇的作用域,所以我们也是禁止使用该方法的