Skip to content

运算符

运算符是用于对值进行操���的符号。理解运算符及其优先级,是写出正确表达式的基础。

🎯 算术运算符#

基本运算#

// 加减乘除
console.log(10 + 3) // 13
console.log(10 - 3) // 7
console.log(10 * 3) // 30
console.log(10 / 3) // 3.3333...
// 取余(模运算)
console.log(10 % 3) // 1
console.log(-10 % 3) // -1(符号跟被除数)
// 指数运算(ES2016)
console.log(2 ** 3) // 8
console.log(4 ** 0.5) // 2(开平方)

自增自减#

let a = 5
// 后置:先返回原值,再自增
console.log(a++) // 5
console.log(a) // 6
// 前置:先自增,再返回新值
console.log(++a) // 7
console.log(a) // 7
// 自减同理
let b = 5
console.log(b--) // 5
console.log(--b) // 3

🔶 避免在复杂表达式中使用自增自减,容易造成困惑:

// 不推荐
let x = 1
const result = x++ + ++x + x++ // 难以理解
// 推荐:拆分成多个语句
let y = 1
y += 1
const step1 = y
y += 1
const step2 = y
// ...

加号的特殊性#

加号既是算术运算符,也是字符串连接符:

// 数字相加
console.log(5 + 3) // 8
// 字符串连接
console.log('Hello' + ' ' + 'World') // "Hello World"
// 🔶 混合运算��陷阱!)
console.log('5' + 3) // "53"(字符串)
console.log(5 + '3') // "53"(字符串)
console.log(5 + 3 + '2') // "82"(先算 5+3=8,再连接)
console.log('2' + 5 + 3) // "253"(从左到右都是连接)
// 强制数值运算
console.log(+'5' + 3) // 8
console.log(Number('5') + 3) // 8

比较运算符#

相等比较#

// == 宽松相等(会类型转换)
console.log(5 == '5') // true
console.log(0 == false) // true
console.log(null == undefined) // true
console.log('' == false) // true
// === 严格相等(不转换类型)
console.log(5 === '5') // false
console.log(0 === false) // false
console.log(null === undefined) // false

最佳实践:始终使用 ===!==,避免隐式类型转换带来的意外。

大小比较#

// 数值比较
console.log(5 > 3) // true
console.log(5 >= 5) // true
console.log(3 < 5) // true
console.log(3 <= 3) // true
// 字符串比较(按 Unicode 码点)
console.log('a' < 'b') // true
console.log('abc' < 'abd') // true
console.log('10' < '9') // true!('1' < '9')
// 混合比较(字符串转��值)
console.log('10' > 9) // true(10 > 9)
console.log('10' > '9') // false(字符串比较)

特殊值比较#

// NaN 与任何值比较都是 false
console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
console.log(NaN > 0) // false
console.log(NaN < 0) // false
// null 和 undefined
console.log(null == undefined) // true
console.log(null === undefined) // false
console.log(null > 0) // false
console.log(null < 0) // false
console.log(null >= 0) // true!(null 转为 0)

逻辑运算符#

与或非#

// && 逻辑与
console.log(true && true) // true
console.log(true && false) // false
console.log(false && true) // false
// || 逻辑或
console.log(true || false) // true
console.log(false || true) // true
console.log(false || false) // false
// ! 逻辑非
console.log(!true) // false
console.log(!false) // true
console.log(!0) // true
console.log(!'') // true
console.log(!null) // true

短路求值#

逻辑运算符不一定返回布尔值,而是返回决定结果的那个值:

// && 返回第一个假值,或最后一个值
console.log('hello' && 'world') // "world"
console.log('' && 'world') // ""
console.log(null && 'world') // null
console.log(1 && 2 && 3) // 3
// || 返回第一个真值,或最后一个值
console.log('' || 'default') // "default"
console.log('hello' || 'default') // "hello"
console.log(0 || null || 'last') // "last"
console.log(0 || '' || false) // false

实际应用#

// 默认值
function greet(name) {
name = name || '游客'
return `你好,${name}`
}
// 条件执行
const user = { name: '张三' }
user && console.log(user.name) // "张三"
// 短路保护
const config = null
const port = config && config.port // undefined(不会报错)
// 链式取值(旧写法)
const street = user && user.address && user.address.street

空值合并运算符 ??#

ES2020 引入的 ?? 只在值为 nullundefined 时才取默认值:

// || 的问题:0 和空字符串会被误判
console.log(0 || 100) // 100(可能不是预期)
console.log('' || 'default') // "default"
// ?? 只对 null/undefined 生效
console.log(0 ?? 100) // 0
console.log('' ?? 'default') // ""
console.log(null ?? 'default') // "default"
console.log(undefined ?? 'default') // "default"
// 实际场景
function setVolume(level) {
level = level ?? 50 // 允许设置为 0
console.log(`音量:${level}`)
}
setVolume(0) // "音量:0"
setVolume() // "音量:50"

位运算符#

位运算符将操作数转为 32 位整数进行运算。

基本位运算#

// & 按位与
console.log(5 & 3) // 1
// 0101 & 0011 = 0001
// | 按位或
console.log(5 | 3) // 7
// 0101 | 0011 = 0111
// ^ 按位异或
console.log(5 ^ 3) // 6
// 0101 ^ 0011 = 0110
// ~ 按位取反
console.log(~5) // -6
// ~0101 = 1010...(32位补码)
// << 左移
console.log(5 << 1) // 10
// 0101 << 1 = 1010
// >> 有符号右移
console.log(5 >> 1) // 2
// 0101 >> 1 = 0010
// >>> 无符号右移
console.log(-1 >>> 0) // 4294967295

实际应用#

// 快速取整(截断小数)
console.log(~~3.7) // 3
console.log(3.7 | 0) // 3
console.log(3.7 >> 0) // 3
// 快速乘除 2 的幂
console.log(5 << 2) // 20(5 * 4)
console.log(20 >> 2) // 5(20 / 4)
// 判断奇偶
console.log(5 & 1) // 1(奇数)
console.log(6 & 1) // 0(偶数)
// 交换两个数(不用临时变量)
let a = 5,
b = 3
a = a ^ b // a = 6
b = a ^ b // b = 5
a = a ^ b // a = 3
console.log(a, b) // 3, 5
// 权限管理
const READ = 1 // 0001
const WRITE = 2 // 0010
const EXECUTE = 4 // 0100
let permission = READ | WRITE // 0011 = 3
console.log(permission & READ) // 1(有读权限)
console.log(permission & EXECUTE) // 0(无执行权限)

赋值运算符#

复合赋值#

let x = 10
x += 5 // x = x + 5 = 15
x -= 3 // x = x - 3 = 12
x *= 2 // x = x * 2 = 24
x /= 4 // x = x / 4 = 6
x %= 4 // x = x % 4 = 2
x **= 3 // x = x ** 3 = 8
// 位运算赋值
x &= 3 // x = x & 3
x |= 4 // x = x | 4
x ^= 1 // x = x ^ 1
x <<= 1 // x = x << 1
x >>= 1 // x = x >> 1

逻辑赋值(ES2021)#

let a = null
let b = 'hello'
let c = ''
// ||= 如果左侧为假值则赋值
a ||= 'default' // a = 'default'
b ||= 'default' // b = 'hello'(不变)
// &&= 如果左侧为真值则赋值
b &&= 'world' // b = 'world'
c &&= 'world' // c = ''(不变)
// ??= 如果左侧为 null/undefined 则赋值
let d = 0
d ??= 100 // d = 0(不变,因为 0 不是 null/undefined)
let e = null
e ??= 100 // e = 100

其他运算符#

条件(三元)运算符#

const age = 18
const status = age >= 18 ? '成年' : '未成年'
console.log(status) // "成年"
// 可以嵌套(但不推荐太深)
const score = 85
const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 60 ? 'C' : 'D'
console.log(grade) // "B"
// 推荐使用 if 或对象映射替代复杂的三元运算

逗号运算符#

// 从左到右求值,返回最后一个值
const result = (1, 2, 3)
console.log(result) // 3
// 常见于 for 循环
for (let i = 0, j = 10; i < j; i++, j--) {
console.log(i, j)
}
// 在一行中执行多个表达式
let x = ((a = 1), (b = 2), a + b)
console.log(x) // 3

可选链运算符 ?.#

安全地访问嵌套属性:

const user = {
name: '张三',
address: {
city: '北京',
},
}
// 传统写法(繁琐)
const zip1 = user && user.address && user.address.zip
// 可选链(简洁)
const zip2 = user?.address?.zip // undefined(不报错)
// 方法调用
const result = user.getName?.() // undefined(不报错)
// 数组访问
const arr = null
console.log(arr?.[0]) // undefined
// 配合空值合并
const city = user?.address?.city ?? '未知城市' // "北京"

typeof 和 instanceof#

// typeof 检查类型
console.log(typeof 42) // "number"
console.log(typeof 'hello') // "string"
console.log(typeof true) // "boolean"
console.log(typeof undefined) // "undefined"
console.log(typeof null) // "object"(历史bug)
console.log(typeof {}) // "object"
console.log(typeof []) // "object"
console.log(typeof function () {}) // "function"
// instanceof 检查原型链
console.log([] instanceof Array) // true
console.log([] instanceof Object) // true
console.log({} instanceof Array) // false
console.log(function () {} instanceof Function) // true

delete 运算符#

const obj = { name: '张三', age: 25 }
delete obj.age
console.log(obj) // { name: "张三" }
// 数组元素删除(留下空位)
const arr = [1, 2, 3]
delete arr[1]
console.log(arr) // [1, empty, 3]
console.log(arr.length) // 3(长度不变)
// 推荐用 splice 删除数组元素
arr.splice(1, 1) // 从索引1删除1个元素

in 运算符#

const obj = { name: '张三' }
console.log('name' in obj) // true
console.log('age' in obj) // false
console.log('toString' in obj) // true(继承的属性)
// 数组中检查索引
const arr = [1, 2, 3]
console.log(0 in arr) // true
console.log(5 in arr) // false
console.log('length' in arr) // true

运算符优先级#

优先级从高到低排列(部分常用):

优先级运算符描述
19()分组
18. [] () ?.成员访问、调用
17new(带参数)创建实例
16++ --(后置)后置自增/减
15! ~ + - ++ --一元运算符
14**指数
13* / %乘除取余
12+ -加减
11<< >> >>>位移
10< <= > >= in比较
9== != === !==相等
8&按位与
7^按位异或
6|按位或
5&&逻辑与
4|| ??逻辑或
3? :条件
2= += -=赋值
1,逗号

实际例子#

// && 优先于 ||
console.log(true || (false && false)) // true
console.log((true || false) && false) // false
// 比较优先于逻辑
console.log(1 + 2 > 2 && 3 < 4) // true
// 等价于 ((1 + 2) > 2) && (3 < 4)
// 一元运算符优先于二元
console.log(!true && false) // false
console.log(!(true && false)) // true
// 🔶 不确定时就加括号!
const result = a > b ? a : c > d ? c : d
// 推荐明确写出
const result2 = a > b ? a : c > d ? c : d

常见陷阱#

🙋 连续比较不是数学意义#

// 数学上:1 < 2 < 3 是对的
console.log(1 < 2 < 3) // true,但原因是...
// 1 < 2 = true
// true < 3 = 1 < 3 = true
console.log(3 > 2 > 1) // false!
// 3 > 2 = true
// true > 1 = 1 > 1 = false
// 正确写法
console.log(1 < 2 && 2 < 3) // true

🙋 + 和 - 的一元用法#

// + 转数值
console.log(+'42') // 42
console.log(+'hello') // NaN
console.log(+true) // 1
console.log(+new Date()) // 时间戳
// - 转负数值
console.log(-'42') // -42
// 常见写法
const timestamp = +new Date()
const num = +inputValue || 0

🙋 ?? 不能和 && || 直接混用#

// 语法错误,需要加括号明确优先级
// console.log(a || b ?? c) // SyntaxError
console.log((a || b) ?? c) // OK
console.log(a || (b ?? c)) // OK

总结#

类别运算符要点
算术+ - * / % **注意 + 的字符串连接
比较== === != !== > <始终用 ===
逻辑&& || !理解短路求值
空值?? ?.安全处理 null/undefined
位运算& | ^ ~ << >>用于性能优化和权限管理
赋值= += -= &&= ??=逻辑赋值是 ES2021 新增
其他typeof instanceof类型和原型链检查

核心建议