JavaScript 代码规范
TIP
- 计算机科学中只有两个难题:缓存失效和命名。 —— Phil Karlton
- 任何人都能写出计算机能够理解的代码,只有好程序员才能写出人能够理解的代码。—— Martin Flower
JavaScript 代码规范旨在提高代码的可读性、可维护性和一致性。通过遵循统一的规范,团队可以避免不必要的错误,并让代码更易于理解和维护。以下是一些常见的 JavaScript 代码规范,涵盖了变量命名、缩进、注释、函数、对象等方面。
1. 变量命名规范
使用有意义的、描述性的变量名
- 变量名应能够反映其用途。避免使用没有意义的单字母或缩写(如
x
、y
、temp
)。
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. 代码缩进
- 使用 2 或 4 个空格来缩进代码。不要使用 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
数组使用扩展运算符
- 使用扩展运算符代替
concat
或push
等方法来合并数组或创建新数组。
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」
或其他类似插件javascriptgetUserPosts // 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 保证动词的统一性
常用的动词有get
、set
、read
、 create
、add
、update
、reset
、 delete
、 remove
等。
javascript
getQuestion
getUserPosts
getUsers
// bad 有很多近意动词,选一个一直用,不要变来变去
getQuestion
returnUsers
retrieveUsers
函数或方法名尽量采用动词或判断性词汇。
函数名一般由一个 动词 加一个 名词 组成,如 getUser
、 getInfo
、 isArray
。
javascript
getFullYear() // 取值
toString() // 转换
isArray() // 判断
11.5 布尔值的命名
布尔值一般用is
、 can
、 has
、 need
等助动词开头,如 isVisible、 hasLicense、 canEvaluate 、shouldAbort
。
返回布尔值的函数或方法,命名规则相同,如 Array.isArray(arr)
。但这样容易出现函数名和变量名冲突的情况,这个时候可以在函数前加check
、get
等区分。
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