• 基本类型

      • 字符串
      • 数值
      • 布尔类型
      • null
      • undefined
    • 复杂类型

      • object
      • array
      • function
      1. const bar = foo
      2. bar[0] = 9
      3. console.log(foo[0], bar[0]) // 9, 9

    引用

    constlet 都是块级作用域,var 是函数级作用域

    • 对所有引用都使用 const,不要使用 var

      1. // bad
      2. var a = 1
      3. var b = 2
      4. // good
      5. const a = 1
      6. const b = 2
    • 如果引用是可变动的,则使用 let

      1. // bad
      2. var count = 1
      3. if (count < 10) {
      4. count += 1
      5. }
      6. // good
      7. let count = 1
      8. if (count < 10) {
      9. count += 1
      10. }

    对象

    • 请使用字面量值创建对象

      1. // bad
      2. const a = new Object{}
      3. // good
      4. const a = {}
    • 别使用保留字作为对象的键值,这样在 IE8 下不会运行

      1. // bad
      2. const a = {
      3. default: {}, // default 是保留字
      4. common: {}
      5. }
      6. // good
      7. const a = {
      8. defaults: {},
      9. common: {}
      10. }
    • 请使用对象方法的简写方式

      1. // bad
      2. const item = {
      3. value: 1,
      4. addValue: function (val) {
      5. return item.value + val
      6. }
      7. }
      8. // good
      9. const item = {
      10. value: 1,
      11. addValue(val) {
      12. return item.value + val
      13. }
      14. }
    • 请使用对象属性值的简写方式

      1. const job = 'FrontEnd'
      2. // bad
      3. const item = {
      4. job: job
      5. }
      6. // good
      7. const item = {
      8. job
      9. }
    • 对象属性值的简写方式要和声明式的方式分组

      1. const job = 'FrontEnd'
      2. const department = 'JDC'
      3. // bad
      4. const item = {
      5. sex: 'male',
      6. job,
      7. age: 25,
      8. department
      9. }
      10. // good
      11. const item = {
      12. job,
      13. department,
      14. sex: 'male',
      15. age: 25
      16. }

    数组

    • 请使用字面量值创建数组

      1. // bad
      2. const items = new Array()
      3. // good
      4. const items = []
    • 向数组中添加元素时,请使用 push 方法

      1. const items = []
      2. // bad
      3. items[items.length] = 'test'
      4. // good
      5. items.push('test')
    • 使用拓展运算符 ... 复制数组

      1. // good
      2. [1, 2, 3].map(x => {
      3. const y = x + 1
      4. })
      5. // good
      6. [1, 2, 3].map(x => x + 1)
      7. // bad
      8. const flat = {}
      9. [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
      10. const flatten = memo.concat(item)
      11. flat[index] = flatten
      12. })
      13. // good
      14. const flat = {}
      15. [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
      16. const flatten = memo.concat(item)
      17. flat[index] = flatten
      18. return flatten
      19. })
      20. // bad
      21. inbox.filter((msg) => {
      22. const { subject, author } = msg
      23. if (subject === 'Mockingbird') {
      24. } else {
      25. return false
      26. }
      27. })
      28. // good
      29. inbox.filter((msg) => {
      30. const { subject, author } = msg
      31. if (subject === 'Mockingbird') {
      32. return author === 'Harper Lee'
      33. }
      34. return false
      35. })

    解构赋值

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

      1. // bad
      2. function getFullName (user) {
      3. const firstName = user.firstName
      4. const lastName = user.lastName
      5. return `${firstName} ${lastName}`
      6. }
      7. // good
      8. function getFullName (user) {
      9. const { firstName, lastName } = user
      10. return `${firstName} ${lastName}`
      11. }
      12. // better
      13. function getFullName ({ firstName, lastName }) {
      14. return `${firstName} ${lastName}`
      15. }
    • 当需要使用数组的多个值时,请同样使用解构赋值

      1. const arr = [1, 2, 3, 4]
      2. // bad
      3. const first = arr[0]
      4. const second = arr[1]
      5. // good
      6. const [first, second] = arr
    • 函数需要回传多个值时,请使用对象的解构,而不是数组的解构

      1. // bad
      2. function doSomething () {
      3. return [top, right, bottom, left]
      4. }
      5. // 如果是数组解构,那么在调用时就需要考虑数据的顺序
      6. const [top, xx, xxx, left] = doSomething()
      7. // good
      8. function doSomething () {
      9. return { top, right, bottom, left }
      10. }
      11. // 此时不需要考虑数据的顺序
      12. const { top, left } = doSomething()

    字符串

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

      1. // bad
      2. const department = "JDC"
      3. // good
      4. const department = 'JDC'
    • 字符串太长的时候,请不要使用字符串连接符换行 \,而是使用 +

      1. const str = '凹凸实验室 凹凸实验室 凹凸实验室' +
      2. '凹凸实验室 凹凸实验室 凹凸实验室' +
      3. '凹凸实验室 凹凸实验室'
    • 程序化生成字符串时,请使用模板字符串

      1. const test = 'test'
      2. // bad
      3. const str = ['a', 'b', test].join()
      4. // bad
      5. const str = 'a' + 'b' + test
      6. // good
      7. const str = `ab${test}`
    • 请使用函数声明,而不是函数表达式

      1. // bad
      2. const foo = function () {
      3. // do something
      4. }
      5. // good
      6. function foo () {
      7. // do something
      8. }
    • 不要在非函数代码块中声明函数

      1. // bad
      2. if (isUse) {
      3. function test () {
      4. // do something
      5. }
      6. }
      7. // good
      8. let test
      9. if (isUse) {
      10. test = () => {
      11. // do something
      12. }
      13. }
    • 不要使用 arguments,可以选择使用 ...

      1. // bad
      2. function test () {
      3. const args = Array.prototype.slice.call(arguments)
      4. return args.join('')
      5. }
      6. // good
      7. function test (...args) {
      8. return args.join('')
      9. }

    原型

    • 使用 class,避免直接操作 prototype

      1. // bad
      2. function Queue (contents = []) {
      3. this._queue = [..contents]
      4. }
      5. Queue.prototype.pop = function () {
      6. const value = this._queue[0]
      7. this._queue.splice(0, 1)
      8. return value
      9. }
      10. // good
      11. class Queue {
      12. constructor (contents = []) {
      13. this._queue = [...contents]
      14. }
      15. pop () {
      16. const value = this._queue[0]
      17. this._queue.splice(0, 1)
      18. return value
      19. }

    模块

    • 使用标准的 ES6 模块语法 importexport

      1. // bad
      2. const util = require('./util')
      3. module.exports = util
      4. // good
      5. import Util from './util'
      6. export default Util
      7. // better
      8. import { Util } from './util'
      9. export default Util
      1. // bad
      2. import * as Util from './util'
      3. // good
      4. import Util from './util'

    迭代器

    • 不要使用 iterators

      1. const numbers = [1, 2, 3, 4, 5]
      2. // bad
      3. let sum = 0
      4. for (let num of numbers) {
      5. sum += num
      6. }
      7. // good
      8. let sum = 0
      9. numbers.forEach(num => sum += num)
      10. // better
      11. const sum = numbers.reduce((total, num) => total + num, 0)

    对象属性

    • 使用 . 来访问对象属性

      1. const joke = {
      2. name: 'haha',
      3. age: 28
      4. }
      5. // bad
      6. const name = joke['name']
      7. // good
      8. const name = joke.name

    变量声明

    • 声明变量时,请使用 constlet 关键字,如果没有写关键字,变量就会暴露在全局上下文中,这样很可能会和现有变量冲突,另外,也很难明确该变量的作用域是什么。这里推荐使用 const 来声明变量,我们需要避免全局命名空间的污染。

      1. // bad
      2. demo = new Demo()
      3. // good
      4. const demo = new Demo()
    • 将所有的 constlet 分组

      1. // bad
      2. let a
      3. const b
      4. let c
      5. const d
      6. let e
      7. // good
      8. const b
      9. const d
      10. let a
      11. let c
      12. let e
    • var 存在变量提升的情况,即 var 声明会被提升至该作用域的顶部,但是他们的赋值并不会。而 constlet 并不存在这种情况,他们被赋予了

      1. function example () {
      2. console.log(notDefined) // => throws a ReferenceError
      3. }
      4. function example () {
      5. console.log(declareButNotAssigned) // => undefined
      6. var declaredButNotAssigned = true
      7. }
      8. function example () {
      9. let declaredButNotAssigned
      10. console.log(declaredButNotAssigned) // => undefined
      11. declaredButNotAssigned = true
      12. }
      13. function example () {
      14. console.log(declaredButNotAssigned) // => throws a ReferenceError
      15. console.log(typeof declaredButNotAssigned) // => throws a ReferenceError
      16. const declaredButNotAssigned = true
      17. }
    • 匿名函数的变量名会提升,但函数内容不会

      1. function example () {
      2. console.log(anonymous) // => undefined
      3. anonymous()
      4. var anonymous = function () {
      5. console.log('test')
      6. }
      7. }
    • 命名的函数表达式的变量名会被提升,但函数名和函数函数内容并不会

      1. function example() {
      2. console.log(named) // => undefined
      3. named() // => TypeError named is not a function
      4. superPower() // => ReferenceError superPower is not defined
      5. var named = function superPower () {
      6. console.log('Flying')
      7. }
      8. }
      9. function example() {
      10. console.log(named) // => undefined
      11. named() // => TypeError named is not a function
      12. var named = function named () {
      13. console.log('named')
      14. }
      15. }

    分号

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

    标准特性

    为了代码的可移植性和兼容性,我们应该最大化的使用标准方法,例如优先使用 string.charAt(3) 而不是 string[3]

    eval()

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

    with() {}

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

    for-in 循环

    推荐使用 for in 语法,但是在对对象进行操作时,容易忘了检测 hasOwnProperty(key),所以我们启用了 ESLintguard-for-in 选项

    不要修改内置对象,如 和 Array