使用 && 和 || 进行属性取值保护的核心是利用短路特性:&& 将可能为空的对象放左侧以避免访问错误,|| 提供默认值但需注意假值误判,?? 更适合空值合并;组合时应将轻量判断放左、耗时操作放右,并避免嵌套过深或误用导致逻辑错误。

直接用 && 和 || 做属性取值保护,核心是让“可能出错”或“可能为空”的操作落在右侧,靠短路跳过它——前提是左侧能快速、安全地判断真假。
用 && 防止访问空值或未定义属性
当对象或中间属性可能为 null、undefined、0、"" 时,把它们放 && 左边,后面链式取值就不会执行:
-
user && user.profile && user.profile.name:只要user是假值,后面两个点操作完全不运行,不会报Cannot read property 'profile' of null -
data?.items && data.items.length > 0中的&&是补充判断,?.已防空,但&&可进一步过滤空数组等“真值但无意义”的情况 - 注意:
0 && obj.name会短路,但0是合法数值,别误以为“只要不是null就该继续”。必要时改用obj != null && obj.name
用 || 提供安全默认值
当期望值可能为假值但仍有效(如 0、false、""),|| 不适合——它会把 0 || 10 当成 10。此时应优先考虑空值合并 ??;但如果明确只处理 null/undefined,|| 可简化写法:
-
config.timeout || 3000:仅当config.timeout是null或undefined时才用3000;若配置存的是0,会被当成假,错误 fallback - 更稳妥写法:
config.timeout ?? 3000,??只在左值严格等于null或undefined时生效 -
user.role || 'guest'在角色字段约定不为0或空字符串时可用,否则需加额外判断
组合使用实现条件性计算
把轻量判断放左边,耗时/有副作用的操作放右边,真正跳过执行:
-
isLoggedIn() && fetchUserData():用户未登录,fetchUserData根本不调用,省请求、避报错 -
hasPermission('edit') && saveDraft():权限检查快,保存动作重,短路可避免无效写入 - 避免写成
saveDraft() && hasPermission('edit')——函数先执行了,短路就失去意义
避开常见陷阱
短路不是万能胶,用错反而引入 bug 或降低可读性:
-
arr && arr[0] && arr[0].id看似安全,但若arr[0]是0或false,id就取不到——这时应改用可选链:arr?.[0]?.id - 嵌套超过三层(如
a && b && c && d && expensive())会让逻辑难追踪,V8 引擎也可能放弃优化,不如拆成if语句 -
obj && obj.method()中,如果method不存在,仍会报错——短路只跳过整个右侧表达式,但obj.method的属性读取已在括号外发生。应写成obj?.method?.()或先检查方法是否存在










