短路特性使&&和||返回最后一个被求值的操作数,且仅右侧操作数可被跳过;应将轻量、高失败率(&&)或高成功率(||)条件置左,耗时操作置右,并警惕隐式转换与副作用。

短路特性在 && 和 || 中的实际表现
JavaScript(以及多数 C 风格语言)中,&& 和 || 不是单纯返回布尔值,而是返回「最后一个被求值的操作数」。关键在于:一旦能确定整个表达式结果,后续操作数就不再执行——这就是短路。比如 false && expensiveFn() 根本不会调用 expensiveFn;true || expensiveFn() 同样跳过调用。
把耗时操作放在短路“右侧”才能真正跳过
短路只对右侧操作数生效,左侧永远会被求值。所以优化的核心是:把开销小、失败概率高(对 &&)或成功概率高(对 ||)的条件放左边,把可能耗时的操作(如 DOM 查询、正则匹配、函数调用)放右边。
-
if (obj && obj.method && obj.method()):如果obj为 falsy,obj.method和obj.method()都不会执行——安全且高效 -
if (isCached() || fetchFromAPI()):缓存命中时,fetchFromAPI()完全不触发 - 反例:
if (getHeavyData().length > 0 && isValid())—— 即使isValid()很快,getHeavyData()每次都执行,失去短路意义
警惕隐式转换导致的意外短路
短路基于「真值/假值」判断,不是严格布尔值。比如空数组 []、对象 {} 是 truthy,而 0、''、null、undefined、NaN 是 falsy。这容易引发误判:
-
if (arr.length && arr[0].id):如果arr.length === 0,短路生效;但如果arr = [null],arr.length是 1(truthy),但arr[0].id会报Cannot read property 'id' of null - 更稳妥写法:
if (Array.isArray(arr) && arr.length > 0 && arr[0]?.id),利用?.进一步防御 - 避免依赖副作用:不要写
flag && doSomething()来代替if (flag) doSomething(),可读性和调试性差,且 IDE 可能警告「Expression has no effect」
短路不解决所有性能问题,别过度依赖
短路只能跳过「执行」,不能跳过「解析」或「闭包捕获」。比如 cond && (() => { /* heavy */ })(),箭头函数本身仍被创建(虽未调用),若该函数很大或频繁构造,仍有内存开销。
- 真正高频或复杂逻辑,应封装为独立函数并按需调用,而非塞进短路表达式
- 涉及异步(
await)时,&&/||无法短路 await 表达式本身:await a() && await b()中,a()总是等待完成才判断是否执行b();想实现异步短路,得用if+await - V8 等引擎对简单短路优化很好,但嵌套过深(如
a && b && c && d && e())可能影响内联和 JIT 编译,实测不如拆成清晰的 if 分支
短路是好工具,但它的价值只在「右侧确实可能被跳过」时才成立——先确认哪部分真慢、哪部分常为假/真,再调整顺序。否则只是让代码更难 debug。










