卫语句是将“不满足就停”的逻辑前置到函数开头,需满足位置靠前、条件取反、立即终止三条件,适用于参数校验、权限验证、依赖检查等拦路型场景,显著降低嵌套与理解成本。

卫语句不是加一层判断,而是把“不满足就停”的逻辑提前写在函数开头。主流程不再被层层 if 包裹,异常路径和正常路径自然分离,读代码时一眼看清“什么情况不能往下走”,也一眼看清“剩下就是该干的事”。
卫语句怎么写才真正起作用
关键不在语法,而在判断顺序和退出动作。它必须满足三个条件:位置靠前、条件取反、立即终止。
- 放在函数最开始,所有校验集中前置,不穿插在业务逻辑中间
- 检查的是“不该继续”的条件,比如 if !data 而不是 if data
- 一旦命中,立刻 return 或 throw,不执行后续任何语句
哪些地方最适合用卫语句处理异常
不是所有 if 都该改,重点是那些“拦路型”校验——它们不参与业务计算,只决定能不能进主流程。
- 参数合法性检查:空值、类型错误、必填字段缺失
- 权限与状态前置验证:用户未登录、角色无权限、资源已被删除
- 外部依赖可用性判断:服务不可达、配置未加载、缓存失效且无法重建
对比嵌套式写法,卫语句实际省了什么
表面看只是少了几层缩进,实质是降低了理解成本和出错概率。
- 不用再数 else 对应哪个 if,缩进层级从 4 层直降到 0 层
- 新增一个校验项,只需加一行 if + throw,无需调整已有结构
- 主逻辑区域不再需要反复做 null 检查,变量可直接使用
- 单元测试更容易覆盖边界路径,每个 guard 自成一个独立失败场景
容易踩的坑和应对建议
用得不好,卫语句也会变成新问题。
- 别把业务分支当卫语句:比如“用户是 VIP 就打折”属于主逻辑,不是 guard
- 避免重复抛出同类异常:统一错误码或消息格式,方便上层捕获处理
- 复杂校验别硬塞进一行:提取成私有方法,如 if !isValidEmail(user.email) { throw ... }
- 日志要跟上:在 throw 前记录关键上下文,否则排查时只剩“某处报错了”











