Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

    • js 编码指南
      • js 代码规范
        • 单行代码块
        • 大括号风格
        • 变量命名
        • 拖尾逗号
        • 逗号空格
        • 逗号风格
        • 计算属性的空格
        • 拖尾换行
        • 函数调用
        • 缩进
        • 对象字面量的键值缩进
        • 构造函数首字母大写
        • 构造函数的参数
        • 链式调用
        • 空行
        • 链式赋值
        • 变量声明
        • 分号
        • 代码块空格
        • 操作符的空格
      • js 语言规范
        • 类型
        • 引用
        • 对象
        • 数组
        • 解构赋值
        • 字符串
        • 函数
        • 原型
        • 模块
        • 迭代器
        • 对象属性
        • 变量声明
        • Hoisting
        • 分号
        • 标准特性
        • eval()
        • with() {}
        • for-in 循环
        • 修改内置对象的原型
    • 日期使用斜杠 点 中划线分隔的不同
    • forEach 会改变原数组值吗
    • 前端表单验证常用的正则表达式 - reg
    • JS 如何取得 URL 里的参数
    • JavaScript 数组去重
    • JavaScript 循环中断研究与总结-关键字篇
    • JavaScript 循环中断研究与总结-用法篇
    • js 中的 Error
    • 跳出 forEach
    • Location 对象
    • Date 方法预览
    • Reg 正则中的问题
    • JavaScript toFixed() 方法
    • query 和 params 的使用区别
    • axios post 请求中下载文件流
    • 实用的 js 技巧
    • JS 之数组的几个不 low 操作
    • 深入浅出深拷贝与浅拷贝
    • 如何实现一个深拷贝
    • 使用 iframe 中的一些问题
    • 在 js 中更好地使用数组
    • echarts 在坐标轴两侧各增加一格坐标
    • 从头认识js的事件循环模型
    • moment 根据周截至日算出指定月有几周及开始结束日期
    • 正则 reg 中 /number 的用法
    • 正则 reg 中 match 和 exec 异同
  • TypeScript

  • Vue

  • ElementUI

  • React

  • AntD

  • 前端
  • JavaScript
Henry
2019-09-05
目录

js 编码指南

# js 代码规范

# 单行代码块

在单行代码块中使用空格

不推荐

function foo () {return true}
if (foo) {bar = 0}
1
2

推荐

function foo() { return true }
if (foo) { bar = 0 }
1
2

# 大括号风格

在编程过程中, 大括号风格与缩进风格紧密联系, 用来描述大括号相对代码块位置的方法有很多. 在 JavaScript 中, 主要有三种风格, 如下:

  • One True Brace Style
if (foo) {
  bar()
} else {
  baz()
}
1
2
3
4
5
  • Stroustrup
if (foo) {
  bar()
}
else {
  baz()
}
1
2
3
4
5
6
  • Allman
if (foo)
{
  bar()
}
else
{
  baz()
}
1
2
3
4
5
6
7
8

我们团队约定使用 One True Brace Style 风格

# 变量命名

当命名变量时, 主流分为驼峰式命名(variableName)和下划线命名(variable_name)两大阵营.

团队约定使用驼峰式命名

# 拖尾逗号

在 ECMAScript5 里面, 对象字面量中的拖尾逗号是合法的, 但在 IE8(非 IE8 文档模式)下, 当出现拖尾逗号, 则会抛出错误.

拖尾逗号的例子:

var foo = {
  name: 'foo',
  age: '22',
}
1
2
3
4

拖尾逗号的好处是, 简化了对象和数组添加或删除元素, 我们只需要修改新增的行即可, 并不会增加差异化的代码行数.

因为拖尾逗号有好也有不好, 所以团队约定允许在最后一个元素或属性与闭括号 ] 或 } 在不同行时, 可以(但最好不要)使用拖尾逗号. 当在同一行时, 禁止使用拖尾逗号.

# 逗号空格

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

不推荐

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

推荐

var foo = 1, bar = 2
1

# 逗号风格

逗号分隔列表时, 在 JavaScript 中主要有两种逗号风格:

  • 标准风格, 逗号放置在当前行的末尾
  • 逗号前置风格, 逗号放置在下一行的开始位置

团队约定使用标准风格

不推荐

var foo = 1
,
bar = 2

var foo = 1
, bar = 2

var foo = ['name'
          , 'age']
1
2
3
4
5
6
7
8
9

推荐

var foo = 1,
  bar = 2

var foo = ['name',
            'age']
1
2
3
4
5

# 计算属性的空格

团队约定在对象的计算属性内, 禁止使用空格

不推荐

obj['foo' ]
obj[ 'foo']
obj[ 'foo' ]
1
2
3

推荐

obj['foo']
1

# 拖尾换行

在非空文件中, 存在拖尾换行是一个常见的 UNIX 风格, 它的好处是可以方便在串联和追加文件时不会打断 Shell 的提示. 在日常的项目中, 保留拖尾换行的好处是, 可以减少版本控制时的代码冲突.

不推荐

function func() {
  // do something
}
1
2
3

推荐

function func() {
  // do something
}
// 此处是新的一行
1
2
3
4

# 函数调用

为了避免语法错误, 团队约定在函数调用时, 禁止使用空格

不推荐

fn ()
fn
()
1
2
3

推荐

fn()
1

# 缩进

代码保持一致的缩进, 是作为工程师的职业素养. 但缩进用两个空格, 还是四个空格, 是用 Tab 还是空格呢? 这样的争论太多了, 也得不出答案. 本规范结合了市面上优秀的开源项目, 姑且约定使用 空格 来缩进, 而且缩进使用两个空格.

# 对象字面量的键值缩进

团队约定对象字面量的键和值之间不能存在空格, 且要求对象字面量的冒号和值之间存在一个空格

不推荐

var obj = { 'foo' : 'haha' }
1

推荐

var obj = { 'foo': 'haha' }
1

# 构造函数首字母大写

在 JavaScript 中 new 操作符用来创建某个特定类型的对象的一个实例, 该类型的对象是由一个构造函数表示的. 由于构造函数只是常规函数, 唯一区别是使用 new 来调用. 所以我们团队约定构造函数的首字母要大小, 以此来区分构造函数和普通函数.

不推荐

var fooItem = new foo()
1

推荐

var fooItem = new Foo()
1

# 构造函数的参数

在 JavaScript 中, 通过 new 调用构造函数时, 如果不带参数, 可以省略后面的圆括号. 但这样会造成与整体的代码风格不一致, 所以团队约定使用圆括号

不推荐

var person = new Person
1

推荐

var person = new Person()
1

# 链式调用

链式调用如果放在同一行, 往往会造成代码的可读性差, 但有些时候, 短的链式调用并不会影响美观. 所以本规范约定一行最多只能有四个链式调用, 超过就要求换行.

# 空行

空白行对于分离代码逻辑有帮助, 但过多的空行会占据屏幕的空间, 影响可读性. 团队约定最大连续空行数为 2

不推荐

var a = 1



var b = 2
1
2
3
4
5

推荐

var a = 1

var b = 2
1
2
3

# 链式赋值

链式赋值容易造成代码的可读性差, 所以团队约定禁止使用链式赋值

不推荐

var a = b = c = 1
1

推荐

var a = 1
var b = 1
var c = 1
1
2
3

# 变量声明

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

不推荐

var a, b, c
1

推荐

var a
var b
var c
1
2
3

# 分号

JavaScript 在所有类 C 语言中是比较独特的, 它不需要在每个语句的末尾有分号. 在很多情况下, JavaScript 引擎可以确定一个分号应该在什么位置然后自动添加它. 此特征被称为 自动分号插入 (ASI), 被认为是 JavaScript 中较为有争议的特征.

团队中对于是否应该使用分号, 也有许多争论, 本规范推荐不使用分号, 因为我们认为好的工程师应该知道什么时候该加, 什么时候不该加.

相关参考 :semi (opens new window)

# 代码块空格

一致性是任何风格指南的重要组成部分. 虽然在哪里放置块的开括号纯属个人偏好, 但在整个项目中应该保持一致. 不一致的风格将会分散读者阅读代码的注意力.

团队约定代码块前要添加空格

不推荐

if (a){
  b()
}

function a (){}
1
2
3
4
5

推荐

if (a) {
  b()
}

function a() {}
1
2
3
4
5

# 操作符的空格

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

不推荐

var sum = 1+2
1

推荐

var sum = 1 + 2
1

# js 语言规范

JavaScript 是一种客户端脚本语言, 这里列出了编写 JavaScript 时需要遵守的规则.

# 类型

  • 基本类型

    • 字符串
    • 数值
    • 布尔类型
    • null
    • undefined
    const foo = 1
    let bar = foo
    
    bar = 9
    
    console.log(foo, bar) // 1, 9
    
    1
    2
    3
    4
    5
    6
  • 复杂类型

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

# 引用

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

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

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

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

# 对象

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

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

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

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

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

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

# 数组

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

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

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

    // 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]
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • 使用数组的 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
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43

# 解构赋值

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

    // 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}`
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  • 当需要使用数组的多个值时, 请同样使用解构赋值

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

    // 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()
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

# 字符串

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

    // bad
    const department = "JDC"
    
    // good
    const department = 'JDC'
    
    1
    2
    3
    4
    5
  • 程序化生成字符串时, 请使用模板字符串

    const test = 'test'
    
    // bad
    const str = ['a', 'b', test].join()
    
    // bad
    const str = 'a' + 'b' + test
    
    // good
    const str = `ab${test}`
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 函数

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

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

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

    arguments 只是一个类数组, 而 ... 是一个真正的数组

    // bad
    function test() {
      const args = Array.prototype.slice.call(arguments)
      return args.join('')
    }
    
    // good
    function test(...args) {
      return args.join('')
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • 不要更改函数参数的值

    // bad
    function test(opts) {
      opts = opts || {}
    }
    
    // good
    function test(opts = {}) {
      // ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# 原型

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

    // 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
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

# 模块

  • 使用标准的 ES6 模块语法 import 和 export

    // bad
    const util = require('./util')
    module.exports = util
    
    // good
    import Util from './util'
    export default Util
    
    // better
    import {
      Util
    } from './util'
    export default Util
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • 不要使用 import 的通配符 * , 这样可以确保你只有一个默认的 export

    // bad
    import * as Util from './util'
    
    // good
    import Util from './util'
    
    1
    2
    3
    4
    5

# 迭代器

  • 不要使用 iterators

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

# 对象属性

  • 使用 . 来访问对象属性

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

# 变量声明

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

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

      // bad
      let a
      const b
      let c
      const d
      let e
    
      // good
      const b
      const d
      let a
      let c
      let e
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

# Hoisting

  • var 存在变量提升的情况, 即 var 声明会被提升至该作用域的顶部, 但是他们的赋值并不会. 而 const 和 let 并不存在这种情况, 他们被赋予了 Temporal Dead Zones, TDZ (opens new window)

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

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

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

# 分号

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

    关于应不应该使用分号的讨论有很多, 本规范认为非必要的时候, 应该不使用分号, 好的 JS 程序员应该清楚场景下是一定要加分号的.

    // bad
    const test = 'good';
    (function () {
      const str = 'hahaha';
    })()
    
    // good
    const test = 'good'
    ;(() => {
      const str = 'hahaha'
    })()
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

# 标准特性

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

# eval()

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

# with() {}

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

# for-in 循环

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

对数组进行 for in 的时候, 顺序是不固定的

# 修改内置对象的原型

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

编辑 (opens new window)
#Js#Guidelines
上次更新: 5/27/2023, 1:02:05 PM
日期使用斜杠 点 中划线分隔的不同

日期使用斜杠 点 中划线分隔的不同→

最近更新
01
version 1.15
07-01
02
version 1.14
06-27
03
version 1.13
06-27
更多文章>
Theme by Vdoing | Copyright © 2017-2023 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式