4、JavaScript规范:变量命名、函数设计原则、条件与循环优化、错误处理规范

JavaScript 这门语言,灵活是真灵活,坑也是真不少。我带过不少团队,发现代码质量的分水岭往往不在用了什么框架,而在于最基础的写法习惯。今天咱们就聊聊这四个核心点,都是我在实际项目中摔过跟头才总结出来的。

4.1 变量命名:别让后来人猜谜语

我见过最离谱的变量名是什么?abc,还有 data1data2。你想想看,三个月后你自己回来看这段代码,能记得 data1 是用户列表还是订单金额吗?

命名原则其实就三条:

  • 语义化:看到名字就知道它存什么。比如 userListlist 好,isLoadingflag 好。
  • 统一风格:变量用驼峰 camelCase,常量用大写 MAX_COUNT,类名用帕斯卡 PascalCase
  • 避免缩写:除非是业界共识(比如 i 做循环索引),否则别自己造缩写。我见过有人写 usrInf,猜了半天是 user information。

我个人习惯的命名对照表:

类型 推荐写法 不推荐写法
布尔值 isVisiblehasPermission visiblepermission
数组 userListitems userArrdata
函数 getUserByIdhandleClick getdoSomething
常量 API_BASE_URLMAX_RETRY baseUrlmax

小技巧:命名时试着读出来。如果读起来像一句话,那就是好名字。比如 user.isActive 读作「用户是活跃的」,很自然。而 user.act 读作「用户.活动」?怪怪的。

4.2 函数设计原则:一个函数只做一件事

这个原则听起来简单,做起来难。我在项目中遇到过一段代码,一个函数干了三件事:验证表单、发送请求、更新页面状态。结果后来需求变了,只想改验证逻辑,但不敢动,因为怕影响后面两件事。

函数设计的三个要点:

  • 单一职责:一个函数只做一件事。如果函数名里出现了「和」字,比如 validateAndSubmit,那大概率该拆了。
  • 参数不超过三个:参数多了,调用方容易搞错顺序。我建议用对象传参,比如 createUser({ name, age, email }),清晰又灵活。
  • 避免副作用:函数最好只通过返回值影响外部,而不是偷偷修改全局变量。嗯,这里要注意,Array.sort 会改变原数组,很多人踩过这个坑。
// 不推荐:一个函数做太多事
function processOrder(order) {
  // 验证
  if (!order.id || !order.amount) throw new Error('订单不完整');
  // 计算
  const total = order.amount * 1.1;
  // 发送
  api.send(order.id, total);
  // 记录日志
  log('订单处理完成');
}

// 推荐:拆分成小函数
function validateOrder(order) {
  if (!order.id || !order.amount) throw new Error('订单不完整');
}

function calculateTotal(amount) {
  return amount * 1.1;
}

function processOrder(order) {
  validateOrder(order);
  const total = calculateTotal(order.amount);
  api.send(order.id, total);
  log('订单处理完成');
}

我曾经接手过一个项目,有个函数叫 handleEverything,里面 300 多行。改一个 bug 要花半天时间理清逻辑。后来我花了两天重构,拆成 12 个小函数,每个不超过 20 行。测试好写了,bug 也少了。

4.3 条件与循环优化:少写 if-else,多用早期返回

条件判断写不好,代码就像一团乱麻。你想想看,嵌套四五层的 if-else,读起来得多痛苦?

优化条件判断的几个套路:

  • 早期返回(Early Return):把异常情况先处理掉,剩下的就是正常逻辑。说白了,就是「先排除干扰项」。
  • 用对象或 Map 替代 switch:当条件分支很多时,查表比写一长串 switch 更清晰。
  • 循环里别做重复计算:比如 arr.length 在循环条件里每次都会计算,提前存到变量里。
// 不推荐:嵌套地狱
function getDiscount(user) {
  if (user) {
    if (user.isVip) {
      if (user.level > 3) {
        return 0.8;
      } else {
        return 0.9;
      }
    } else {
      return 1;
    }
  } else {
    return 1;
  }
}

// 推荐:早期返回 + 查表
function getDiscount(user) {
  if (!user) return 1;
  if (!user.isVip) return 1;

  const discountMap = {
    1: 0.95,
    2: 0.9,
    3: 0.85,
    4: 0.8,
  };

  return discountMap[user.level] || 1;
}

循环优化小贴士:如果只是遍历数组,用 for...offorEach 比传统 for 循环更可读。但如果需要提前跳出循环,for 循环配合 break 还是最合适的。

4.4 错误处理规范:别让用户看到「undefined is not a function」

错误处理是 JavaScript 里最容易忽视的部分。很多人只写「快乐路径」,异常情况一概不管。结果线上出了问题,用户看到白屏,开发者一脸懵。

错误处理的三个层次:

  • 防御性编程:对不确定的数据做检查。比如从 API 拿到的数据,可能字段缺失,用 ?.?? 操作符可以优雅处理。
  • try-catch 要精准:别把整个函数包在 try-catch 里,那样会掩盖真正的 bug。只包住可能出错的代码块。
  • 错误信息要有用:别只写 Error: 出错了,要带上上下文。比如 Error: 获取用户列表失败,userId: 123
// 不推荐:错误信息太模糊
try {
  const data = await api.getUser(id);
  render(data);
} catch (e) {
  console.log('出错了');
}

// 推荐:精准捕获 + 有用信息
async function loadUser(id) {
  if (!id) {
    throw new Error('loadUser 需要传入有效的 id');
  }

  let data;
  try {
    data = await api.getUser(id);
  } catch (e) {
    // 区分网络错误和业务错误
    if (e.status === 404) {
      throw new Error(`用户 ${id} 不存在`);
    }
    throw new Error(`获取用户 ${id} 失败: ${e.message}`);
  }

  if (!data || !data.name) {
    throw new Error(`用户 ${id} 的数据结构异常`);
  }

  render(data);
}

我曾经在一个支付项目里,因为没做错误处理,用户支付成功后页面卡住了。排查了半天,发现是后端返回的字段名变了,前端没做兼容。从那以后,我对所有外部数据都加了校验,宁可多写几行代码,也不能让用户看到白屏。

说白了,JavaScript 规范不是束缚,而是保护。保护你自己不被自己写的代码坑到,也保护你的队友能安心接手你的代码。这些习惯养成了,写代码会越来越顺手。