1:前言
这是一个大家看了很熟悉又很陌生的一个运算操作符,有用过吗?它有着什么样的深层含义呢?和我们熟悉的 || 操作符又有什么区别?带着这些问题我们开始探究它究竟在做些什么。
2:深入理解 JavaScript 中的空值合并运算符 ?? 与逻辑或运算符
在 JavaScript 中, ?? 是"空值合并运算符" (Nullish Coalescing Operator) ,而 || 是逻辑或运算符。虽然这两个运算符都用于提供默认值,但它们在处理空值的方式上有显著区别。
2.1: 空值合并运算符 ??
?? 运算符返回其左侧操作数,若该操作数为 null 或 undefined,则返回右侧操作数。它只在遇到这两种"空值"时才会返回右侧的值。
示例:
js
let a = null
let b = 'Hello'
console.log(a ?? b) // 输出: "Hello"
let c = undefined
let d = 'World'
console.log(c ?? d) // 输出: "World"
let e = 0
let f = 'Default'
2.2.:逻辑或运算符 ||
|| 运算符返回其左侧操作数,若该操作数为假值(如 false、0、""、null、undefined 或 NaN),则返回右侧操作数。
示例:
js
let g = null
let h = 'Hello'
console.log(g || h) // 输出: "Hello"
let i = 0
let j = 'Default'
console.log(i || j) // 输出: "Default"
2.3:解决什么痛点
假值混乱,我们实际中使用 || 运算符会有一些不期望的结果出现,有的时候我们只要 null 与 undefined 判假即可。
2.4:运算优先级问题
以下是 JavaScript 运算符的优先级表,按优先级从高到低排列。优先级高的运算符会先于优先级低的运算符执行。
优先级 | 运算符 | 描述 |
---|---|---|
1 | () |
括号,强制优先级 |
2 | . |
成员访问 |
2 | [] |
数组元素访问 |
2 | new |
创建实例 |
2 | ++ -- |
自增自减(前置) |
3 | ++ -- |
自增自减(后置) |
4 | ! ~ - + typeof |
一元运算符 |
5 | ** |
幂运算符 |
6 | * / % |
乘法、除法、取余 |
7 | + - |
加法、减法 |
8 | << >> >>> |
位移运算符 |
9 | < <= > >= |
比较运算符 |
10 | == != === !== |
相等与不相等 |
11 | & |
按位与 |
12 | ^ |
按位异或 |
13 | ` | ` |
14 | && |
逻辑与 |
15 | ` | |
16 | ?? |
空值合并运算符 |
17 | ?: |
三元运算符 |
18 | = += -= *= /= 等 |
赋值运算符 |
19 | yield |
生成器的 yield |
20 | in |
会员运算符 |
20 | instanceof |
实例运算符 |
21 | , |
逗号运算符 |
注意事项
- 运算符优先级 :优先级高的运算符会先于优先级低的运算符执行。例如,
*
和/
的优先级高于+
和-
。 - 括号 :使用括号
()
可以强制改变运算顺序。 - 结合性:运算符的结合性决定了在优先级相同的情况下,运算符的计算顺序(例如,从左到右或从右到左)。
3:深层含义与区别
3.1:处理的值:
?? 仅关注 null 和 undefined ,|| 关注所有假值。
3.2:使用场景:
使用 ?? 时,通常希望提供一个默认值,仅在变量未定义或为 null 时使用。
使用 || 时,通常希望处理所有可能的假值情况。
4:应用实例
4.1:配置对象
在处理配置对象时,可能会有一些默认值需要设置。使用 ?? 可以确保我们只在缺少必要配置时才使用默认值
js
// 获取对应的配置
function getConfig(config) {
const defaultConfig = {
host: 'localhost',
port: 3000,
useHttps: false
}
return {
host: config.host ?? defaultConfig.host,
port: config.port ?? defaultConfig.port,
useHttps: config.useHttps ?? defaultConfig.useHttps
}
}
// 默认配置
const userConfig = { port: 8080, useHttps: undefined }
// 需处理的配置
const finalConfig = getConfig(userConfig)
console.log(finalConfig)
// 输出: { host: "localhost", port: 8080, useHttps: false }
在这个例子中,useHttps 被设置为 false,因为用户没有提供有效的值。
4.2:用户输入处理
在处理用户输入时,可能会有多种输入类型。使用 ?? 和 || 可以帮助我们更好地管理这些输入。
js
// 处理输出
function processInput(input) {
const defaultInput = 'Default Input'
// 使用 ?? 确保处理 null 和 undefined
const finalInput = input ?? defaultInput
// 使用 || 处理其他假值
return finalInput || 'Fallback Input'
}
console.log(processInput(null)) // 输出: "Default Input"
console.log(processInput(undefined)) // 输出: "Default Input"
console.log(processInput(0)) // 输出: "Fallback Input"
console.log(processInput('')) // 输出: "Fallback Input"
console.log(processInput('Valid Input')) // 输出: "Valid Input"
在这个例子中,input 为 null 或 undefined 时,返回默认输入;而当 input 为 0 或空字符串时,则返回备用输入。
5:结论
?? 运算符提供了更精确的控制,避免因假值(如 0 或 "")而错误地替换有效值。
|| 运算符则适合处理所有假值的情况。
通过上述示例和分析,希望你能更深入地理解 ?? 和 || 运算符的使用场景及其区别。如果你还有其他更巧妙的使用案例,请与我分享!