JavaScript中是否有“空值合并”运算符?
技术背景
在JavaScript编程里,处理变量可能为null
或undefined
的情况极为常见。为了给这类可能缺失值的变量赋予默认值,各种方法和运算符应运而生。长久以来,开发者用逻辑或运算符||
来达成简单的默认值赋值,但该方法也存在缺陷。随着时间流逝,为了更精准地处理null
和undefined
情形,JavaScript推出了空值合并运算符??
。
实现步骤
旧方法:使用逻辑或运算符 ||
过去,要给变量指定默认值,通常用逻辑或运算符||
。示例如下:
1
| var whatIWant = someString || "Cookies!";
|
这种方法会把所有转为布尔值是false
的值都认定为无效值,接着使用第二个操作数。不过,它可能和其他语言(像C#)中的空值合并运算符行为有差异。比如:
1 2 3 4 5
| alert(Boolean(null)); alert(Boolean(undefined)); alert(Boolean(0)); alert(Boolean("")); alert(Boolean("false"));
|
新方法:使用空值合并运算符 ??
JavaScript如今支持空值合并运算符??
。当左侧操作数是null
或undefined
时,它返回右侧操作数;反之,则返回左侧操作数。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const response = { settings: { nullValue: null, height: 400, animationDuration: 0, headerText: '', showSplashScreen: false } };
const undefinedValue = response.settings?.undefinedValue ?? 'some other default'; const nullValue = response.settings?.nullValue ?? 'some other default'; const headerText = response.settings?.headerText ?? 'Hello, world!'; const animationDuration = response.settings?.animationDuration ?? 300; const showSplashScreen = response.settings?.showSplashScreen ?? true;
|
自定义函数
若||
运算符不符合需求,可以自定义函数:
1 2 3 4 5 6 7
| function $N(value, ifnull) { if (value === null || value === undefined) return ifnull; return value; }
var whatIWant = $N(someString, 'Cookies!');
|
考虑 NaN
的自定义函数
若要排除NaN
,可使用以下自定义函数:
1 2 3 4 5 6 7 8 9 10 11
| function coalesce() { var i, arg; for (i = 0; i < arguments.length; i++) { arg = arguments[i]; if (arg !== null && arg !== undefined && (typeof arg !== 'number' || arg.toString()!== 'NaN')) { return arg; } } return null; }
|
逻辑空赋值运算符 ??=
还可使用逻辑空赋值运算符??=
,它结合了空值合并运算符??
和赋值运算符=
。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let a; let b = null; let c = false;
a ??= true; b ??= true; c ??= true;
let x = ["foo"]; let y = { foo: "fizz" };
x[0] ??= "bar"; x[1] ??= "bar"; y.foo ??= "buzz"; y.bar ??= "buzz";
|
核心代码
空值合并运算符示例
1 2 3 4 5 6 7 8 9
| const var1 = undefined; const var2 = "fallback value"; const result = var1 ?? var2; console.log(`Nullish coalescing results in: ${result}`);
const result_old = (var1!== null && var1!== undefined)? var1 : var2; console.log(`Nullish coalescing results in: ${result_old}`);
|
逻辑空赋值运算符示例
1 2 3 4 5
| const car = { speed: 20 }; car.speed ??= 5; console.log(car.speed); car.name??= "reno"; console.log(car.name);
|
最佳实践
链式使用空值合并运算符
可链式使用空值合并运算符,按从左到右的顺序选取第一个非null
、非undefined
的值:
1
| const value = first ?? second ?? third ?? "default";
|
与可选链运算符结合
空值合并运算符常和可选链运算符?.
一同使用,用于安全访问对象属性:
1
| const undefinedValue = response.settings?.undefinedValue ?? 'some other default';
|
常见问题
||
与 ??
有何差异?
||
会返回第一个“真值”,要是没有真值则返回最后一个值,不管它是什么。??
仅返回第一个非null
、非undefined
的值,若无此类值则返回最后一个值,不管它是什么。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let F1; let F2 = null; let F3 = 0; let F4 = ''; let F5 = parseInt('Not a number (NaN)'); let T1 = 3; let T2 = 8;
console.log(F1 || F2 || F3 || F4 || F5 || T1 || T2); console.log(F1 || F2 || F3 || F4 || F5);
console.log(F1 ?? F2 ?? F3 ?? F4 ?? F5 ?? T1); console.log(F1 ?? F2);
|
NaN
怎么处理?
NaN
既非null
也非undefined
,所以使用??
运算符时它不会被当作空值处理。若要把NaN
当作空值,就得自定义函数来处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function coalesce() { var i, undefined, arg; for (i = 0; i < arguments.length; i++) { arg = arguments[i]; if (arg!== null && arg!== undefined && (typeof arg!== 'number' || arg.toString()!== 'NaN')) { return arg; } } return null; }
function coalesce_short() { var i, arg; for (i = 0; i < arguments.length; i++) { arg = arguments[i]; if (arg!= null && arg === arg) { return arg; } } return null; }
|
浏览器兼容性如何?
大多数主流浏览器的较新版本都支持空值合并运算符。你可以通过 Can I Use 查看具体的浏览器兼容性情况。要是需要支持较旧的浏览器,可使用Babel等工具对代码进行编译。Babel 7.8.0 及以上版本默认支持空值合并运算符。