Skip to content

运算符

运算符是 JavaScript 里最基础的表达式构件。它们不仅用来做加减乘除,还影响类型转换、默认值处理、条件判断和赋值行为。

先抓住最重要的分类

开发中最常接触的运算符大致可以分成:

  • 算术运算:+-*/%**
  • 比较运算:><>=<====!==
  • 赋值运算:=+=??=
  • 逻辑运算:||&&!??
  • 自增自减:++--
  • 条件运算:condition ? a : b

算术运算

基本算术

js
console.log(1 + 2) // 3
console.log(5 - 2) // 3
console.log(3 * 4) // 12
console.log(8 / 2) // 4
console.log(7 % 3) // 1
console.log(2 ** 3) // 8

其中:

  • % 表示取余
  • ** 表示幂运算

+ 的两种语义

数字相加

js
console.log(1 + 2) // 3

字符串拼接

只要有一侧是字符串,+ 往往就会走字符串拼接:

js
console.log('1' + 2) // 12
console.log(2 + '1') // 21
console.log('hello ' + 'world') // hello world

这也是 + 最容易引发误解的地方。

为什么 2 + 2 + '1''41'

js
console.log(2 + 2 + '1') // 41
console.log('1' + 2 + 2) // 122

因为表达式会按顺序计算:

  • 2 + 2 先得到 4
  • 4 + '1' 再走字符串拼接

一元 +

一元 + 常用于显式转数字:

js
console.log(+'42') // 42
console.log(+true) // 1
console.log(+'') // 0

它和 Number(value) 的目的接近,但可读性上通常 Number() 更明确。

比较运算

常见比较

js
console.log(2 > 1) // true
console.log(2 >= 2) // true
console.log(1 < 2) // true

相等判断优先用 ===

js
console.log(1 === 1) // true
console.log(1 === '1') // false

相比之下,== 会触发隐式类型转换:

js
console.log(1 == '1') // true
console.log(false == 0) // true

现代代码里,除非非常清楚自己要利用哪条转换规则,否则优先使用:

  • ===
  • !==

赋值运算

基本赋值

js
let count = 1
count = 2

复合赋值

js
let total = 10

total += 5
total *= 2

console.log(total) // 30

常见写法包括:

  • +=
  • -=
  • *=
  • /=
  • %=

逻辑赋值

近几年更常见的还有:

js
let name = ''
name ||= 'anonymous'

let size = 0
size ??= 100

区别在于:

  • ||=:左值为假值时才赋值
  • ??=:左值为 nullundefined 时才赋值

逻辑运算符

||

|| 会返回第一个真值;如果都不是真值,返回最后一个值。

js
console.log('A' || 'B') // A
console.log('' || 'fallback') // fallback
console.log(0 || 100) // 100

&&

&& 会返回第一个假值;如果都是真值,返回最后一个值。

js
console.log(1 && 2) // 2
console.log(0 && 2) // 0
console.log('A' && 'B') // B

!

! 用于取反:

js
console.log(!true) // false
console.log(!0) // true

有时也会看到 !!value,它常被用来转布尔值:

js
console.log(!!'hello') // true
console.log(!!null) // false

??

?? 返回第一个“非空值”,也就是第一个不是 nullundefined 的值。

js
console.log(null ?? 'fallback') // fallback
console.log(undefined ?? 'fallback') // fallback
console.log(0 ?? 100) // 0

这也是它和 || 最关键的区别:

js
console.log(0 || 100) // 100
console.log(0 ?? 100) // 0

如果 0false、空字符串都是合法值,通常更适合用 ?? 提供默认值。

js
const values = [null, undefined, 0, '', false]

for (const value of values) {
  console.log(value || '默认值')
}

for (const value of values) {
  console.log(value ?? '默认值')
}

第一段会将所有假值替换为默认值;第二段只替换 nullundefined

?.

?.(可选链)会在左侧为 nullundefined 时停止访问并返回 undefined,适合读取可选属性或调用可选方法。

js
const result = response?.data?.items?.[0]
callback?.()

它不会吞掉其他运行时错误,也不应替代对业务必填数据的校验。

短路行为

||&& 都会短路,也就是在结果已经确定时停止后续计算。

js
true || console.log('never run')
false && console.log('never run')

这也是它们经常被用来做轻量分支控制的原因,但不要因此滥用成难读的“技巧代码”。

自增与自减

js
let count = 1

count++
console.log(count) // 2

count--
console.log(count) // 1

前置和后置的差异主要体现在“表达式返回值”:

js
let a = 1
console.log(++a) // 2

let b = 1
console.log(b++) // 1
console.log(b) // 2

如果不是特别依赖返回值,优先写成更直白的 count += 1 也没问题。

优先级

运算符优先级决定表达式先算哪一部分。

js
const result = 2 + 3 * 4
console.log(result) // 14

这里先算乘法,再算加法。

不过在实际开发里,更重要的原则不是背表,而是:

  • 一旦表达式稍复杂,就主动加括号
  • 用括号表达意图,而不是让读者猜优先级
js
const result = (a ?? 0) + (b ?? 0)

??&& / ||

??&&|| 混用时,通常需要显式加括号:

js
const result = (a && b) ?? fallback

否则会直接报语法错误。

位运算符

位运算符包括:

  • &
  • |
  • ^
  • ~
  • <<
  • >>
  • >>>

它们更偏底层二进制操作,日常前端业务代码里使用频率不高。除非明确在处理位标记、权限编码或二进制数据,否则通常不需要优先依赖它们。

使用建议

  • 相等比较优先用 ===!==
  • 给默认值时,先判断应该用 || 还是 ??
  • 表达式稍复杂就加括号,不要依赖读者记忆优先级。
  • 看到结果“很怪”的表达式时,优先检查是不是隐式类型转换和 + 拼接导致的。

基于 MIT 许可发布