Skip to content

JavaScript 代码规范

TIP

  • 计算机科学中只有两个难题:缓存失效和命名。 —— Phil Karlton
  • 任何人都能写出计算机能够理解的代码,只有好程序员才能写出人能够理解的代码。—— Martin Flower

JavaScript 代码规范旨在提高代码的可读性、可维护性和一致性。通过遵循统一的规范,团队可以避免不必要的错误,并让代码更易于理解和维护。以下是一些常见的 JavaScript 代码规范,涵盖了变量命名、缩进、注释、函数、对象等方面。

1. 变量命名规范

使用有意义的、描述性的变量名

  • 变量名应能够反映其用途。避免使用没有意义的单字母或缩写(如 xytemp)。
javascript
// Bad
let x = 10

// Good
let userCount = 10

使用驼峰命名法(CamelCase)

  • JavaScript 中常用的命名法是驼峰命名法,首字母小写,后面每个单词的首字母大写。
javascript
// Bad
let user_name = 'John'

// Good
let userName = 'John'

常量使用全大写命名

  • 对于不可变的常量,使用全大写字母并用下划线分隔。
javascript
// Good
const MAX_USERS = 100

2. 代码缩进

  • 使用 24 个空格来缩进代码。不要使用 tab 键混合缩进。
javascript
// Good
function sum(a, b) {
  return a + b
}

3. 语句结束使用分号

  • JavaScript 中分号是可选的,但为了避免自动插入分号机制(ASI,Automatic Semicolon Insertion)引发的问题,建议始终在语句末尾加分号。
javascript
// Good
let userName = 'Alice'

4. 代码长度

  • 每行代码不应超过 80-100 个字符,确保代码易于阅读和维护。可以通过换行来保持行长度限制。
javascript
// Good
const isUserEligibleForDiscount =
  user.age > 18 && user.membershipStatus === 'active' && user.purchaseHistory.length > 10

5. 函数

函数命名

  • 函数名应以动词开头,表明函数的作用。
javascript
// Good
function getUserInfo() {
  // ...
}

function setUserName(name) {
  // ...
}

使用箭头函数(在适当场景)

  • 在不需要 this 关键字的场景下,使用箭头函数可以提高代码的简洁性。
javascript
// Good
const sum = (a, b) => a + b

函数参数的合理控制

  • 函数的参数尽量保持在 3 个以内,超出时可以考虑传入对象。
javascript
// Good
function createUser({ name, age, email }) {
  // ...
}

6. 对象与数组

对象属性使用简写

  • 在 ES6 中,当属性名与变量名相同时,可以使用对象简写语法。
javascript
// Good
const name = 'Alice'
const user = { name } // 相当于 { name: name }

对象和数组的解构赋值

  • 使用解构可以提高代码的可读性,避免反复访问对象或数组属性。
javascript
// Good
const user = { name: 'Alice', age: 25 }
const { name, age } = user

数组使用扩展运算符

  • 使用扩展运算符代替 concatpush 等方法来合并数组或创建新数组。
javascript
// Good
const arr1 = [1, 2]
const arr2 = [3, 4]
const combined = [...arr1, ...arr2]

7. 条件判断

使用严格相等(===!==

  • 严格相等检查避免了类型转换带来的潜在问题。
javascript
// Bad
if (x == 0) {
  // Do something
}

// Good
if (x === 0) {
  // Do something
}

短路评估

  • 在逻辑判断中使用短路评估来减少代码的冗余。
javascript
// Good
const isValid = user && user.isActive

// Better
const isValid = user?.isActive

使用三元运算符进行简单的条件赋值

  • 对于简单的条件操作,使用三元运算符代替 if-else 语句。
javascript
// Good
const userStatus = isLoggedIn ? 'Logged In' : 'Guest'

8. 注释

使用单行注释和多行注释

  • 单行注释:对于简单的说明或标注,使用 //
  • 多行注释:对于较为复杂的逻辑或需要详细解释的代码块,使用 /* */
javascript
// This is a single line comment

/*
  This is a multi-line comment.
  It explains the following block of code.
*/
function calculateTax(income) {
  // Tax calculation logic
}

避免无意义的注释

  • 注释应该解释“为什么”做某件事,而不是“是什么”或“怎么做”。不要写与代码功能重复的注释。
javascript
// Bad
// This is a function to get the user name
function getUserName() {
  //...
}

// Good
// Fetches the user name from the database if user is logged in
function getUserName() {
  //...
}

9. 常见最佳实践

避免魔法数字

  • 魔法数字指的是在代码中直接使用的数字,而没有上下文解释其意义。应将其定义为常量,并给予有意义的名称。
javascript
// Bad
if (score > 60) {
  // Pass
}

// Good
const PASSING_SCORE = 60
if (score > PASSING_SCORE) {
  // Pass
}

避免全局变量

  • 尽量避免在全局作用域中声明变量,防止与其他脚本冲突。

使用模板字符串

  • 使用 ES6 的模板字符串(反引号 ``)可以避免复杂的字符串拼接,并且可以插入变量和表达式。
javascript
// Good
const message = `Hello, ${userName}. You have ${messages.length} new messages.`

提前返回减少嵌套

  • 函数中使用“提前返回”来减少嵌套和复杂度。
javascript
// Bad
function processUser(user) {
  if (user) {
    if (user.isActive) {
      // Do something
    }
  }
}

// Good
function processUser(user) {
  if (!user || !user.isActive) return
  // Do something
}

补充:

10. 下划线

下划线是有特定意义的,不要乱用

javascript
this._myPrivateMethod = function () {
  /* ... */
}
// bad
const _someGlobalVar = 1

11. 有意义的命名

11.1 使用具描述性的名字

  • 命名要精确表意,不能太宽泛,更不能词不达意

    • 同一个事物可能有多个单词适配,选最合适的
    • 同一个词有多种含义
  • 使用业务术语。应避免从电脑的视角去命名,而是应该从人类认识事物的角度去命名

  • 尽量避免用缩略语

  • 避免使用黑话。

  • 单词拼对。推荐安装「Code Spell Checker」或其他类似插件

    javascript
    getUserPosts
    // bad 含义过于宽泛,不精确
    getUserData
    getUserInfo
    // bad 不要用单个单词的变量,如果只是很小的范围内使用的临时变量则无大碍
    global.d = new Date()

11.2 用词应尽量精简,无法精简长些也无妨,不能为了精简而放弃语义

javascript
findUserByNameOrEmail
setUserLoggedInTrue
// bad 选词应该尽量精简,但必须保证语义的确定性
findUser
getUserFriend
// bad "FromDatabase" 提供了多少附加信息? 这种可以精简掉
getUserFriendFromDatabase

11.3 在上下文中保证意义明确

这一条可以认为是上面两条的结合,命名不应该重复上下文信息

javascript
Class Employee {
  constructor (name) {
    // good
    this.name = name;
    // bad 因为本身就处在 Employee 这个上下文中,信息冗余
    this.employeeName = name;
  }
}
// 这里在 name 前加 employee 是有必要的,因为已经脱离了 Employee 这个上下文
const employeeName = new Employee('gavin').name;

11.4 保证动词的统一性

常用的动词有getsetreadcreateaddupdateresetdeleteremove等。

javascript
getQuestion
getUserPosts
getUsers
// bad 有很多近意动词,选一个一直用,不要变来变去
getQuestion
returnUsers
retrieveUsers

函数或方法名尽量采用动词或判断性词汇。
函数名一般由一个 动词 加一个 名词 组成,如 getUsergetInfoisArray

javascript
getFullYear() // 取值
toString() // 转换
isArray() // 判断

11.5 布尔值的命名

布尔值一般用iscanhasneed等助动词开头,如 isVisible、 hasLicense、 canEvaluate 、shouldAbort
返回布尔值的函数或方法,命名规则相同,如 Array.isArray(arr)。但这样容易出现函数名和变量名冲突的情况,这个时候可以在函数前加checkget等区分。

javascript
const hasApple = checkHasApple(fruits, 'apple')
// hasApple       是否包含苹果
// checkHasApple  判断是否包含苹果

11.6 数值的命名

首选有意义的简短命名,如 width、 length、 count,如果没有合适的就采用 numberOfXXX、 xxxCount 之类的通用命名

javascript
width
length
total
maxWidth
numberOfErrors
errorCount

11.7 类名用名词

javascript
class Car {}
new User()
// bad -- 类本来就是一类事物的抽象,需用名词
class MakeCar {}

11.8 字典(Map)的命名

推荐使用 valuesByKey 的方式,如 usersByID

javascript
const usersByID = {
  id12345: { name: 'byted', age: 9 },
  // ...
}
// bad
values // 提供的信息不够充分
keysToValuesMap // 名字里不要体现类型,类型信息交给 TypeScript 记吧
mapOfKeysToValues
mapFromKeysToValues

君子慎独