news 2026/10/8 3:49:38

jstips 详解 JavaScript 短路求值:用 与 || 写出更简洁健壮的代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
jstips 详解 JavaScript 短路求值:用 与 || 写出更简洁健壮的代码
  • 教程

【免费下载链接】jstips

This is about useful JS tips!

项目地址:https://gitcode.com/gh_mirrors/js/jstips
点击查看免费下载

短路求值(Short-Circuit Evaluation)是 JavaScript 中&&与||两个逻辑运算符最实用的行为特性:表达式的结果一旦能被第一个操作数确定,第二个操作数就完全不会被执行。本指南以 jstips 第 27 期(_posts/en/javascript/2016-01-27-short-circuit-evaluation-in-js.md)为骨架,结合仓库内多个相关 tip,系统讲解如何用&&替代if、用||设置默认值、安全访问可能为undefined的对象属性,并深入 truthy/falsy、回调守卫与函数式循环等进阶场景。读完你将掌握一套可立即上手的简洁条件表达式写法,并理解其底层求值规则与边界陷阱。

一、什么是短路求值

短路求值的核心规则只有一条:只有当第一个操作数的值不足以决定整个逻辑表达式的结果时,第二个操作数才会被求值(执行)。具体到两个运算符:

  • 对于逻辑与&&:如果第一个操作数求值为false,那么无论第二个操作数是什么,整个表达式的结果都必然是false,因此第二个操作数不会被求值;
  • 对于逻辑或||:如果第一个操作数求值为true,那么整个表达式的结果都必然是true,因此第二个操作数不会被求值。

反过来理解:a && b只有a为真时才需要看b;a || b只有a为假时才需要看b。这正是原文档(_posts/en/javascript/2016-01-27-short-circuit-evaluation-in-js.md)第一段所阐述的定义,也是下面所有实战技巧的理论基础。

二、用&&替代if语句

先定义一组测试条件与两个输出函数(与原文档示例一致):

var test = true; var isTrue = function(){ console.log('Test is true.'); }; var isFalse = function(){ console.log('Test is false.'); };

传统写法需要一个完整的if语句:

// 普通的 if 语句 if(test){ isTrue(); // Test is true }

利用&&的短路特性,当test为true时右侧的isTrue()才会执行,上面的语句可以压缩成一行:

// 上面的语句可以使用 '&&' 写为: ( test && isTrue() ); // Test is true

当test为false时,&&左侧已经决定了整个表达式的结果为false,右侧函数根本不会被调用——这正是我们想要的"条件为真才执行"语义。仓库第 60 期 tip Three useful hacks 中同样收录了这个模式:

if(condition){ dosomething(); } // 等价于 condition && dosomething();

可见这并非孤例,而是社区反复验证的通用写法。

三、用||替代if(!test)语句

把test置为false,传统写法是取反后判断:

test = false; if(!test){ isFalse(); // Test is false. }

利用||的短路特性:当test为false时,左侧已无法确定结果,右侧isFalse()才会执行;当test为true时右侧被跳过。于是等价于一行:

( test || isFalse()); // Test is false.

两种写法输出完全一致,但后者在表达"条件为假才执行"的意图时更加紧凑。&&管"为真时做",||管"为假时做",两者互补。

四、用||为函数参数设置默认值

||最经典的应用场景是给缺失的参数填充默认值:

function theSameOldFoo(name){ name = name || 'Bar' ; console.log("My best friend's name is " + name); } theSameOldFoo(); // My best friend's name is Bar theSameOldFoo('Bhaskar'); // My best friend's name is Bhaskar

调用时不传参数,name为undefined(假值),||触发右侧求值,name被赋为默认值'Bar';传入'Bhaskar'时左侧为真值,直接短路保留原值。

仓库第 60 期 tip 对"变量默认值"的扩展演示更进一步:

var a; console.log(a); //undefined a = a || 'default value'; console.log(a); //default value a = a || 'new value'; console.log(a); //default value

注意最后一步:a已经是'default value'(真值),a || 'new value'左侧短路,a保持原值不变——说明||默认值写法只会在左侧为假值时生效,一旦赋值成功就不会被再次覆盖。

五、用&&安全访问属性,避免报错

访问未定义对象的属性会抛出运行时错误,&&可以充当安全的"守卫":

var dog = { bark: function(){ console.log('Woof Woof'); } }; // 调用 dog.bark(); dog.bark(); // Woof Woof. // 但是当 dog 未定义时,dog.bark() 将会抛出 "Cannot read property 'bark' of undefined." 错误 // 防止这种情况,我们可以使用 &&。 dog && dog.bark(); // 只有当 dog 被定义时才会调用 dog.bark()

原理依然来自短路规则:dog为undefined(假值)时,&&左侧已决定结果为假,右侧dog.bark()根本不会执行,从而避免Cannot read property 'bark' of undefined异常;dog存在时右侧正常调用。

六、深入一:truthy/falsy 是短路求值的判定基础

理解短路求值,必须先理解 JavaScript 的布尔化规则。仓库第 30 期 tip Converting truthy/falsy values to boolean 给出了完整的假值清单与真值示例:

!!"" // false !!0 // false !!null // false !!undefined // false !!NaN // false !!"hello" // true !!1 // true !!{} // true !![] // true

所有假值(false、0、""、null、undefined、NaN)都会让&&短路跳过右侧、让||继续求值右侧;而其余值一律按真值处理。这与第 5 期 tip Differences betweenundefinedandnull中"两者均为 falsy"的结论一致——正因undefined是假值,第四节中的默认值技巧和第五节中的安全访问技巧才能成立。

七、深入二:回调守卫模式 callback && callback(err)

短路求值在异步编程中最常见的应用是"回调守卫":只在回调存在时才调用它。仓库第 54 期 tip How to use optional arguments in functions 中两次使用了这一模式:

// 传统写法 if (err) { return callback && callback(err); } // ES6 写法 if (err && callback) return callback(err);

callback && callback(err)同时完成了两件事:callback为undefined或null时短路跳过,不会抛出callback is not a function异常;callback存在时正常调用并把err传给它。这是对第五节"安全访问"思想的直接延伸——不仅属性可以守卫,函数参数同样可以守卫。

八、深入三:函数式循环中的短路 —— .some 与 .every

短路求值不仅作用于操作数,也体现在数组迭代方法中。仓库第 58 期 tip Breaking or continuing loop in functional programming 指出:for循环可以用break提前终止,而.forEach无法 break;改用.some后,只要回调返回true,遍历立即停止(相当于短路):

[0, 1, 2, 3, 4].some(function(val, i) { if (val === 2) { return true; // break:停止遍历 } console.log(val); // 你的业务代码 }); // 输出: 0, 1

用.every也能达到类似效果,只是需要返回与.some相反的布尔值。这种"返回即短路"的迭代语义,与&&/||的"结果已定即跳过"在思想上完全同源,是短路思维在更高层抽象中的体现。

九、注意事项与边界陷阱

  1. 假值陷阱:name || 'Bar'对''、0、NaN等"有意义的假值"也会强制替换成默认值。如果业务上需要保留0或空字符串,||默认值就不适用,应改用显式判断name === undefined或 ES6 默认参数function foo(name = 'Bar'){}(ES6 默认参数只对undefined生效)。
  2. 可读性权衡:condition && dosomething()适合条件简短、副作用清晰的行内场景;条件复杂时,传统if语句的可读性与可调试性更优,不必强行压缩。
  3. 返回值是操作数本身:a && b的结果不是布尔值,而是被"选中"的那个操作数(可能是a也可能是b的原值)。这在链式访问(如obj.a && obj.a.b && obj.a.b.c)中非常有用,但也要求开发者明确最终拿到的是真值/假值还是具体对象。
  4. 与!!的配合:需要真正布尔结果时,可结合第 30 期 tip 的!!写法:!!(dog && dog.bark)得到标准布尔值,避免结果类型被操作数"污染"。

十、小结

短路求值是 JavaScript 中最实用也最容易被忽视的语言特性之一:&&表达"条件为真才执行"、||表达"条件为假才兜底",两者共同支撑起默认参数、安全属性访问、回调守卫等高频率实战写法。本指南中的全部示例均来自 jstips 仓库(英文原版见 _posts/en/javascript/2016-01-27-short-circuit-evaluation-in-js.md,中文版见 _posts/zh_CN/javascript/2016-01-27-short-circuit-evaluation-in-js.md),并可继续在 Three useful hacks、Converting truthy/falsy values to boolean、Use optional arguments 与 Break or continue loop in functional programming 等相邻 tip 中延伸阅读。掌握了求值规则与假值边界,就能安全、自信地在日常代码中运用这一简洁范式。

  • 教程

【免费下载链接】jstips

This is about useful JS tips!

项目地址:https://gitcode.com/gh_mirrors/js/jstips
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 3:48:14

综合能源系统两阶段随机优化:源荷不确定性场景生成与容量配置实战

直接说结论:这篇论文复现的难度不在“两阶段随机优化”这个数学框架本身,而在“源荷不确定性”如何生成、如何缩减、如何嵌入优化模型而不让求解器直接卡死。我第一次跑通这个模型用了将近三周,中间踩了很多坑,走了不少弯路。这篇…

作者头像 李华
网站建设 2026/10/8 3:48:01

C# WinForms窗体换肤实战:60种ssk皮肤文件接入与避坑指南

简介:这是一份面向C#桌面应用开发者的窗体美化资源包,针对WinForm界面风格单一、缺乏视觉吸引力的问题,提供开箱即用的皮肤方案。包内共92个文件,以61个.ssk皮肤文件为核心,另含6个cs源码、2个dll组件、5个exe示例程序…

作者头像 李华
网站建设 2026/10/8 3:48:00

NVIDIA开源AI Agent权限管控方案:策略引擎构建安全护栏

现在很多团队在接 AI Agent 的时候,都卡在同一个地方:模型本身的输出质量已经不是最大瓶颈,真正让人头疼的是——Agent 一旦拿到工具权限,就像实习生拿到了万能钥匙,你不知道他下一秒会打开哪扇门。上个月我们内部做技…

作者头像 李华
网站建设 2026/10/8 3:47:35

别再把逻辑全塞进main函数:功能函数拆分与代码清晰布局实战

1. 先说现象:一段全是if的main函数是怎么把人逼疯的最近帮一个刚学编程的同事看代码,发现一个特别典型的毛病:半个程序都写在主函数里。功能函数倒是有,但更像是把一堆变量塞给几个“工具人”,main从头到尾贯穿所有细节…

作者头像 李华
网站建设 2026/10/8 3:46:38

本地Embedding与每日自动同步:个人知识库搭建完整复盘

有段时间,我的个人知识管理基本是三个阵地:微信收藏夹、浏览器书签、硬盘里随手存下的 Markdown 碎片。光收藏一时爽,真要找一段之前读过的结论,得在三个地方来回翻。后来我决定认真搭一套个人知识库,把"收藏&quo…

作者头像 李华