4. JavaScript 编码规范:命名规范、注释规范与语句表达式规范

聊到 JavaScript 编码规范,我第一个想说的就是命名。

你想想看,代码写出来是给人看的。机器只关心对错,但人得看懂逻辑。我见过太多项目,变量名全是 abtempdata,三个月后自己都看不懂写了啥。嗯,这其实是个大坑。

4.1 命名规范:让名字自己说话

4.1.1 变量命名

变量名要用小驼峰(camelCase)。说白了就是第一个单词小写,后面每个单词首字母大写。

我个人习惯是:名词或形容词+名词。比如:

// 好的命名
let userName = '张三';
let isLoggedIn = false;
let maxCount = 100;
let shoppingCart = [];

// 糟糕的命名
let a = '张三';
let flag = false;
let num = 100;
let arr = [];

我在项目中遇到过有人用 aaabbb 这种命名,结果代码 review 时被怼得很惨。记住:名字要能表达用途

小技巧:布尔类型的变量,我习惯用 is、has、can 开头。比如 isVisible、hasPermission、canSubmit。一眼就能看出是 true/false。

4.1.2 函数命名

函数名也是小驼峰。但函数是动作,所以要用动词开头。

// 好的函数名
function getUserData() { }
function calculateTotal() { }
function handleClick() { }
function validateEmail() { }

// 糟糕的函数名
function data() { }
function total() { }
function click() { }

我曾经接手过一个项目,有个函数叫 doSomething()。你猜它做了什么?它发了网络请求、更新了 DOM、还改了全局变量。嗯,这种命名等于没命名。

4.1.3 类与构造函数命名

类名用大驼峰(PascalCase)。每个单词首字母都大写。

class UserProfile { }
class ShoppingCart { }
class ApiService { }

为什么?因为看到大驼峰,你就知道这是个类,需要 new 来实例化。这是约定俗成的规矩。

注意:不要用下划线开头或结尾。比如 _privatename_。虽然 JavaScript 允许,但这容易让人误解。我见过有人用 __proto__ 做变量名,结果踩了原型链的坑。

4.2 注释规范:JSDoc 让文档自动生成

注释不是越多越好。好的代码本身就能说明问题。但有些地方,注释是必须的。

4.2.1 什么时候需要注释

  • 复杂的业务逻辑
  • 别人看不懂的算法
  • 临时修复(记得加 TODO)
  • 函数和类的说明

4.2.2 JSDoc 的基本写法

JSDoc 是一种标准化的注释格式。它不光给人看,还能生成文档,IDE 也能识别。

/**
 * 计算购物车总价
 * @param {Array} items - 商品列表
 * @param {number} items[].price - 单价
 * @param {number} items[].count - 数量
 * @param {number} [discount=0] - 折扣,可选,默认0
 * @returns {number} 总价
 */
function calculateTotal(items, discount = 0) {
  let total = items.reduce((sum, item) => {
    return sum + item.price * item.count;
  }, 0);
  return total * (1 - discount);
}

我个人习惯是:每个导出函数都写 JSDoc。内部函数可以简单写。这样团队其他人调用时,鼠标悬停就能看到说明。

4.2.3 常用标签

标签 用途 示例
@param 参数说明 @param {string} name - 用户名
@returns 返回值 @returns {boolean}
@throws 可能抛出的异常 @throws {Error} 当参数无效时
@deprecated 标记废弃 @deprecated 请使用新方法
@example 使用示例 @example calculateTotal([...])
避坑指南:我曾经在一个项目里看到有人写了 200 行的函数,注释只有一行「// 处理数据」。后来重构时,没人敢动那函数。因为根本不知道它到底处理了什么数据。所以,复杂逻辑一定要写清楚「为什么这么做」,而不是「做了什么」。

4.3 语句与表达式规范:写出整洁的代码

4.3.1 分号的使用

JavaScript 有自动分号插入机制。但我不建议依赖它。为什么?因为有些情况会出问题。

// 可能出问题的写法
let a = 1
(function() {
  console.log('hello');
})();

// 上面会被解析成:
let a = 1(function() { ... })();  // 报错!

// 正确的写法
let a = 1;
(function() {
  console.log('hello');
})();

我个人习惯:每行结尾都加分号。虽然有些团队不用分号,但加了更安全,也少了很多争议。

4.3.2 大括号与缩进

大括号不要省略。即使只有一行代码。

// 不推荐
if (condition) doSomething();

// 推荐
if (condition) {
  doSomething();
}

缩进统一用 2 个空格。我见过用 4 个空格的,也见过用 Tab 的。说实话,这都可以。但关键是团队要统一。我们团队用 2 空格,因为嵌套深的时候看起来更清爽。

4.3.3 比较运算符

===!==,不要用 ==!=

// 坑人的 ==
console.log(0 == false);   // true
console.log('' == false);  // true
console.log(null == undefined); // true

// 用 === 更安全
console.log(0 === false);  // false
console.log('' === false); // false

我记得有一次线上 bug,就是因为 == 把空字符串当成了 false,导致判断逻辑出错。从那以后,我要求团队必须用 ===

4.3.4 字符串使用单引号

团队统一用单引号。除非字符串里包含单引号,才用双引号或模板字符串。

const name = '张三';
const message = '他说:"你好"';
const greeting = `你好,${name}`;

4.3.5 避免全局变量

不要污染全局作用域。用 letconst,别用 var

// 不好的做法
var count = 0;  // 全局变量

// 好的做法
const count = 0;  // 块级作用域
经验之谈:我习惯默认用 const。只有确定变量会重新赋值时,才用 let。这样能避免很多意外修改。至于 var,我建议直接忘掉它。

4.4 总结一下

命名规范、注释规范、语句规范,这三件事看起来琐碎,但决定了代码的可维护性。

你想想看,一个项目少则几千行,多则几十万行。如果每个人按自己的习惯写,那代码就是一团乱麻。规范不是限制你,而是保护你。

嗯,最后送大家一句话:写代码时,想象一下三个月后的自己会怎么看这段代码。 如果你自己都看不懂,那别人更看不懂。