JavaScript中赋值表达式前置感叹号的作用及if内使用逻辑解析
旧JavaScript代码片段逻辑解析与优化写法
核心语法原理说明
你看到的两个疑惑点,本质是JavaScript两个基础特性结合出来的早期简写写法:
- 赋值表达式的返回值特性:JavaScript中所有使用单等号的赋值表达式本身是有返回值的,返回值就是赋给左侧变量的实际内容。把赋值放在if括号里的执行顺序是:先执行右侧的取值/运算逻辑、把结果赋值给左侧提前声明的变量、再把刚拿到的赋值结果作为判断条件决定是否进入if代码块。这种写法是早期代码里常见的“减少行数”的简写,但因为和相等判断(
==/===)的视觉差异极小,非常容易让读代码的人看错逻辑。 - 逻辑非操作符的作用:
!是逻辑非操作符,会把后面跟着的值强制转换成布尔类型后再取反:如果后面的值转布尔后是true(比如非空字符串、数字、对象),取反后就是false;如果后面的值转布尔后是false(比如空字符串、undefined、null、0),取反后就是true。
原代码逐行执行的完整逻辑
把每一步的隐含逻辑拆开,原代码实际完成的业务流程是:
- 提前声明两个空值变量
expand和root - 第一行if逻辑:调用jQuery方法取当前DOM节点上的
data-expand属性值,把这个值赋值给expand变量;用!对这个值做取反判断:如果取到的属性值是空、不存在,就走if块把expand默认设为"Yes";如果属性有非空值,就保留取到的实际值,不做默认赋值 - 第二行if逻辑:调用jQuery方法取当前DOM节点上的
data-root属性值,把这个值赋值给root变量;直接判断这个值的布尔真假:如果能取到非空值,就进入块内判断,如果root的值严格等于"Yes",就不管之前expand拿到的是什么值,都强制把expand改成"Yes"
功能等价的优化写法
原代码这种把赋值和判断混在if括号里的写法,本身就是很多前端Lint规则默认拦截的反模式,非常容易引发隐蔽bug(比如后续修改时不小心把单等号写成相等判断,很难第一时间发现)。优化的核心目标是消除歧义,把隐含的业务逻辑显式写出来,降低后续维护的理解成本:
兼容老环境的基础写法
// 先单独取出所有DOM属性值,不和判断逻辑混写 const expandAttr = $curr_section.attr("data-expand"); const rootAttr = $curr_section.attr("data-root"); let expand = null; let root = null; // 给expand设置默认值:没有取到有效值时默认Yes if (!expandAttr) { expand = "Yes"; } else { expand = expandAttr; } // 存储root属性值 root = rootAttr; // root属性为Yes时,强制覆盖expand的值 if (root === "Yes") { expand = "Yes"; }
现代JavaScript简洁写法
利用ES6+的特性进一步简化,同时保持可读性:
const expandAttr = $curr_section.attr("data-expand"); const rootAttr = $curr_section.attr("data-root"); // 逻辑或兜底空值场景,匹配原代码的判断逻辑 let expand = expandAttr || "Yes"; const root = rootAttr; if (root === "Yes") { expand = "Yes"; }
注意:原代码中如果
data-expand属性被设置为"No",会被正常保留;但只要data-root属性值为"Yes",就会强制覆盖expand为"Yes"。这个隐藏逻辑在原代码中非常难一眼识别,优化后的写法把规则显式写在代码里,不需要读代码的人拆解简写逻辑。
内容的提问来源于stack exchange,提问作者espresso_coffee
相关产品推荐
相关产品推荐

