Skip to content

Javascript 风格指南

simplexcspp edited this page Aug 25, 2019 · 18 revisions

1.类型Types

  • 1.1基本类型
    • string
      • 装箱转换
    • number
      • typeof NaN => number
      • NaN === NaN => false
      • Number.isNaN()
      • 0.1 + 0.2 === 0.3 => false
      • 装箱转换
    • boolean
      • 装箱转换
    • null
      • typeof null => object
    • undefined
      • 非js关键字,取值使用void(0)代替
    • symbol
      • 装箱转换
  • 1.2引用类型
    • object
    • array
    • function

2.变量声明References

  • 2.1使用const代替var为主要变量声明方式,eslint规则:prefer-const, no-const-assign, no-var
const num = 1

const arr = []
arr.push(123, 456)
  • 2.2部分需重新分配引用的变量使用let声明
const end = 6
let num = 0
while(num < end) {
    // your code
    num++
}
  • 2.3const, let声明变量存在块级作用域,且不会成为window属性(浏览器宿主环境)
{
    let o1 = 1
    const o2 = 2
}
console.log(o1) // ReferenceError
console.log(o2) // ReferenceError

const a = 1
let b = 2
console.log(window.a) // undefined
console.log(window.b) // undefined
  • 2.4var声明变量为函数作用域,会成为window属性(浏览器宿主环境)

3.对象

  • 3.1使用对象字面量{}方式声明对象,而非使用new Object()方式,eslint规则no-new-object
  • 3.2使用属性简洁表示法定义对象,简洁且描述性更好
const name = 'jack'

// bad
const obj = {
    name: name,
    getName: function (value) {
        return obj.name + value
    }
}

// good
const obj = {
    name,
    getName(value) {
        return obj.name + value
    }
}
  • 3.3使用属性简洁表示法的属性应在对象字面量开头定义,便于区分
const name = 'jack'
const age = 18

//  bad
const obj = {
    id: 1,
    name,
    sex: 'male',
    age
}

// good
const obj = {
    name,
    age,
    sex: 'male',
    id: 1
}
  • 3.4使用属性名表达式表示对象变化的属性名,便于在字面量声明内定义对象所有属性
function getKey(k) {
    return `_${k}`
}

// bad
const obj = {
    name: 'jack',
    age: 18
}
obj[getKey('id')] = 1

// good
const obj = {
    [getKey('id')]: 1,
    name: 'jack',
    age: 18
}
  • 3.5仅当对象属性名为无效标识符时才使用引号属性,便于js引擎解析代码,代码易读及编译器语法高亮显示,eslint规则quote-props
// bad
const obj = {
    'name': 'jack',
    'age': 18,
    'first-name': 'xu'
}

// good
const obj = {
    name: 'jack',
    age: 18,
    'first-name': 'xu'
}
  • 3.6对象不宜直接调用其原型对象Object.prototype上的方法,如:hasOwnProperty, propertyIsEnumerable, isPrototypeOf,防止这些方法被对象的同名方法覆盖。eslint规则no-prototype-builtins
const obj = {
    name: 'jack'
}

// bad
console.log(obj.hasOwnProperty('name'))

// good
console.log(Object.prototype.hasOwnProperty.call(obj, 'name'))

// best
const has = Object.prototype.hasOwnProperty
console.log(has.call(obj, 'name'))
  • 3.7使用扩展运算符...代替Object.assign浅拷贝对象,使用rest参数拷贝对象部分属性。
// very bad
const origin = {
    a: 1,
    b: 2
}
const copy = Object.assign(origin, {c: 3}) // origin已变化, {a: 1, b: 2, c: 3}
delete copy.a // origin再次变化, {b: 2, c: 3}

// bad
const origin = {
    a: 1,
    b: 2
}
const copy = Object.assign({}, origin, { c: 3 })
// orign: {a:1, b: 2}
// cpoy:  {a: 1, b: 2, c: 3}


// good
const origin = {
    a: 1,
    b: 2
}
const copy = { ...origin, c: 3 } 
// { a: 1, b: 2, c: 3 }

const { a, ...noA } = copy
// { b: 2, c: 3 }

4.数组

  • 4.1使用数组字面量[]方式声明数组,而非使用new Array()方式,eslint规则no-array-constructor
  • 4.2使用push往数组添加元素,而非使用直接赋值方式
const arr = []

// bad 
arr[arr.length] = 1

// good
arr.push(1)
  • 4.3使用扩展运算符...复制数组
const arr = [1, 2, 3]

// bad
const copy = []
let i = 0
const len = arr.length

while(i < len) {
    copy[i] = arr[i]
    i++
}

// good
const copy = [...arr]
  • 4.4使用扩展运算符...将可遍历对象(部署Iterator接口)转换为数组
const set = new Set([1, 2, 3])

// good
const list = Array.from(set)

// best
const list = [...set]
  • 4.5使用Array.from将类数组对象转换为数组
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }

// bad
const arr = Array.prototype.slice.call(arrLike)

// good
const arr = Array.from(arrLike)
  • 4.6当映射可遍历对象时,使用Array.from代替...,避免多创建一个临时[]
const set = new Set([1, 2, 3])

// bad
const list = [...set].map(item => item + 1)

// best
const list = Array.from(set, item => item + 1)
  • 4.7在数组方法回调函数中使用return语句, 如果函数体由一个返回表达式的语句组成,并且没有副作用,则可以省略返回。eslint规则:array-callback-return
// good
[1,2,3].map(x => {
    const y = x + 2
    return x * y - 1
})

const arr = [
    {
        x: '1月',
        y: 50
    },
    {
        x: '2月',
        y: 200
    }
]

// bad
const arr2 = arr.filter(item => {
    let { y } = item;
    if (Number(y) || y === 0) {
        return y > 50
    } else {
        return false
    }
})

// good
const arr2 = arr.filter(item => {
    let { y } = item;
    if (Number(y) || y === 0) {
        return y > 50
    }
    return false
})

// bad
const flatArr = [[0, 1], [2, 3], [4, 5]].reduce((acc, curr) => {
    const flatten = acc.concat(curr)
})

// good
const flatArr = [[0, 1], [2, 3], [4, 5]].reduce((acc, curr) => {
    const flatten = acc.concat(curr)
    return flatten
})

  • 4.8数组包含多个元素时,元素之间使用换行书写风格
// bad 
const arr1 = [
    [1, 2], [3, 4], [5, 6]
]

const arr2 = [{
    id: 1,
    name: 'jj'
}, {
    id: 2,
    name: 'jdjd'

}]

const arr3 = [
    2, 3, 4
]

// good
const arr1 = [
    [1, 2],
    [3, 4],
    [5, 6]
]

const arr2 = [
    {
        id: 1,
        name: 'jj'
    },
    {
        id: 2,
        name: 'jdjd'

    }
]

const arr3 = [
    2,
    3,
    4
]

Clone this wiki locally