如果你去问一个工作三五年的前端,逻辑运算符和补码能有什么关系,八成会被当成在聊数学题。我以前也觉得它们一个管条件判断,一个管负数存储,一个给 CPU 看,平时根本不在同一条链路里。直到一次跨端项目排查,让我在模板 :key 里面写了带逻辑运算符的表达式,H5 端一切正常,小程序端却出现数据对不上、节点错乱的“灵异现象”。问题顺着模板语法往下挖,居然一路挖到了补码的符号位和溢出边界上。
这篇不是教科书,也不打算从布尔代数第一章开始念。我想把 &&、||、短路求值、补码加减这几件事放到同一个真实项目背景里说清楚,顺便复盘那个 :key 不支持逻辑运算符的兼容性坑。对写前端、客户端,或者日常会跟跨端模板和位运算打交道的人来说,这几个概念拼在一起并不违和:逻辑运算符决定“走哪条路”,短路逻辑决定“后面那段代码到底跑不跑”,补码决定“走到边界时数字会不会突然变成负数”。三件事看着分散,其实是同一套程序执行逻辑的不同层面。
1. 逻辑运算符:它返回的不一定是布尔值
1.1 从“真/假”到“决定结果的那个值”
先看一行很简单的代码:
javascript复制const a = 1 && 2;
const b = 0 || 'default';
console.log(a); // 2
console.log(b); // 'default'
如果刚接触 JavaScript,大概率会觉得这里写错了。1 && 2 为什么不返回 true?因为 JavaScript 里的逻辑运算符在做完真假判定后,返回的不是布尔值,而是“能够决定整个表达式结果的那个操作数本身”。
具体规则不复杂:
left && right:如果left为真,返回right;如果left为假,返回left。left || right:如果left为真,返回left;如果left为假,返回right。!left:永远返回布尔值,这是唯一一个保证返回true或false的逻辑运算符。
很多人第一次看到这个规则会觉得是语言设计有问题。但正是这种设计,让 const name = user.name || '匿名'; 这种默认值写法成为可能。表达的并不
