前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库运算符优先级 赋值 相等
JavaScript值与类型

a = b === c 到底先算哪一步?优先级会引出哪些 bug?

赋值 = 的优先级比 === 低得多,所以 a = b === c 先比较 b === c,再把 true 或 false 赋给 a。真正出 bug 的通常不是这一句,而是 if (x = 5)、!a === b、flags & 2 === 2 这类写法。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#值与类型
先看核心答案读代码示例
理解线索

和这道题相关的三档优先级

  1. 一元运算!、typeof、一元 + 最先算,只作用于紧跟着的那个值
  2. 比较与相等<、> 高于 ===、==,两者都比位运算 &、| 先算
  3. 赋值=、+= 几乎最后算,只比逗号运算符高,而且从右往左结合

?? 不能和 ||、&& 直接混写,a ?? b || c 是语法错误,必须加括号。这是语言故意设计的,避免大家猜优先级。

核心回答

先记住这个答案

赋值运算符的优先级比严格相等低很多,在所有运算符里只比逗号、yield 这几个高。所以 a = b === c 会先算 b === c,得到一个布尔值,再把它赋给 a,效果等同于 a = (b === c)。这句本身不容易出错,真正坑人的是周边几种写法:条件里把 === 写成 =、把 ! 放在比较前面、位运算和相等混用。实际项目里的规矩很简单:优先级不是一眼能看出来的,就加括号。

  • a = b === c 先比较再赋值
  • ! 的优先级高于 ===
  • &、| 比 === 后算,位运算要加括号
  • 赋值从右往左结合,比较从左往右结合

赋值和相等放在一起时

先看几种一行里同时有赋值、取反和比较的写法,每行的注释写出了引擎实际的分组方式。

实际的分组JavaScript
const b = 1, c = 1
let a
a = b === c // 等价于 a = (b === c)
console.log(a) // true,而不是 1

let x = 0
if (x = 5) console.log('进了 if,x 被改成', x) // 少写了两个等号

const n = 3
console.log(!n === 0) // (!n) === 0 → false === 0 → false
console.log(!(n === 0)) // true
查看输出与解释
true
进了 if,x 被改成 5
false
true

第二段是最常见的 bug。x = 5 是一个赋值表达式,它的值就是 5,5 是真值,所以 if 永远成立,而且顺手把 x 改掉了。ESLint 的 no-cond-assign 规则专门抓这个问题。 第三段是想写「n 不等于 0」,结果写成了 !n === 0。! 是一元运算符,优先级比 === 高,只作用于紧挨着的 n,于是先得到 false,再拿 false 和 0 做严格比较。想表达不等于,直接写 n !== 0。

为什么 a = b === c 不会先赋值
可以这样理解:优先级高的运算符「抓」操作数的力气更大。=== 先把两边的 b 和 c 抓走组成一组,= 只能拿到剩下的整个结果。语言让赋值几乎最后执行,就是为了保证「右边整个算完,再存进左边」。像 total = price * count + fee 这种写法,没人希望先执行 total = price。

结合方向和位运算这两个坑

优先级相同的运算符连在一起时,按结合方向决定先后。比较运算从左往右结合,赋值从右往左结合。另外位运算 &、| 的优先级比相等还低,这一点和很多人的直觉相反。

连续比较和位运算JavaScript
console.log(1 < 2 < 3) // (1 < 2) < 3 → true < 3 → 1 < 3
console.log(3 > 2 > 1) // (3 > 2) > 1 → true > 1 → 1 > 1

const flags = 6 // 二进制 110
console.log(flags & 2 === 2) // flags & (2 === 2) → 6 & 1
console.log((flags & 2) === 2)

let p, q
p = q = 5 // 赋值从右往左结合:p = (q = 5)
console.log(p, q)
查看输出与解释
true
false
0
true
5 5

1 < 2 < 3 看起来像数学里的区间判断,结果是 true 纯属巧合。3 > 2 > 1 就露馅了:先得到 true,true 转成数字是 1,1 > 1 为假。判断区间要写成 a < b && b < c。 flags & 2 === 2 是检查权限位时的经典错误。=== 先算出 true,6 & true 里 true 转成 1,110 & 001 得 0。在 C 语言里也有同样的问题,JavaScript 沿用了这套优先级。

连等赋值要当心
p = q = 5 从右往左执行,先把 5 赋给 q,这个赋值表达式的值是 5,再赋给 p。如果写成 let p = q = 5,只有 p 被声明了,q 在非严格模式下会变成一个意外的全局变量,严格模式下直接报 ReferenceError。
回答前,多想一步

容易答错的地方

以为 a = b === c 会把 b 赋给 a
这是把代码从左往右「读」出来的直觉。引擎是按优先级分组的,=== 先结合,所以 a 拿到的是布尔值。如果本意是赋值后再比较,要写成 (a = b) === c。
把 !a === b 当成 a !== b
! 只取反紧跟着的那个操作数。!a === b 是「a 取反后是否严格等于 b」,和「a 不等于 b」完全是两回事。
觉得背熟优先级表就可以不加括号
背得熟不代表读代码的同事也背得熟。除了四则运算和常见的 &&、|| 组合,涉及位运算、??、三元运算的混合表达式都应该加括号,这也是 ESLint no-mixed-operators 规则的出发点。
试着用自己的话回答

面试官还会怎么问?

a ?? b || c 为什么报错?

规范禁止 ?? 和 ||、&& 在没有括号的情况下直接混用,这是一个语法错误,代码根本不会运行。原因是两种写法的意图都说得通,语言选择让开发者用括号写清楚:(a ?? b) || c 或 a ?? (b || c)。

三元运算和相等放在一起,先算哪个?

相等优先。const label = a === b ? 'same' : 'diff' 会先算 a === b,再根据结果选分支。三元运算的优先级和赋值接近,比所有比较、逻辑运算都低,所以这种写法不用加括号也是对的。

typeof x === 'string' 需要加括号吗?

不需要。typeof 是一元运算符,优先级比 === 高,会先得到类型字符串再比较。容易出问题的是反过来写 typeof x + 'y',它等于 (typeof x) + 'y',而不是对 x + 'y' 求类型。

从一道题,走向一组知识

把知识连起来

值与类型

一元加号 +x 和 Number(x) 有什么区别?

一元 + 和 ! 一样优先级很高,+a === b 会先把 a 转成数字再比较。

值与类型

Object.is 和 === 有什么区别?什么时候非用 Object.is 不可?

优先级决定先比较哪两个值,=== 和 Object.is 的差别则决定比较结果是什么。

参考资料

  • JavaScript:值与类型参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 赋值和相等放在一起时
  3. 结合方向和位运算这两个坑
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑