Javascript中是否有空合并运算符?
例如,在 C# 中,我可以这样做:
String someString = null;
var whatIWant = someString ?? "Cookies!";
我可以为 Javascript 找出的最佳近似值是使用条件运算符:
var someString = null;
var whatIWant = someString ? someString : 'Cookies!';
恕我直言,这有点恶心。我能做得更好吗?
Javascript中是否有空合并运算符?
例如,在 C# 中,我可以这样做:
String someString = null;
var whatIWant = someString ?? "Cookies!";
我可以为 Javascript 找出的最佳近似值是使用条件运算符:
var someString = null;
var whatIWant = someString ? someString : 'Cookies!';
恕我直言,这有点恶心。我能做得更好吗?
更新
JavaScript 现在支持空值合并运算符 (??)。当其左侧操作数为null
or时返回其右侧操作数undefined
,否则返回其左侧操作数。
旧答案
请在使用前检查兼容性。
C# null 合并运算符 ( ??
) 的 JavaScript 等效项使用逻辑 OR ( ||
):
var whatIWant = someString || "Cookies!";
在某些情况下(下文说明)该行为与 C# 的行为不匹配,但这是在 JavaScript 中分配默认/替代值的一般、简洁的方式。
无论第一个操作数的类型如何,如果将其转换为 Boolean 会导致false
,则赋值将使用第二个操作数。请注意以下所有情况:
alert(Boolean(null)); // false
alert(Boolean(undefined)); // false
alert(Boolean(0)); // false
alert(Boolean("")); // false
alert(Boolean("false")); // true -- gotcha! :)
这表示:
var whatIWant = null || new ShinyObject(); // is a new shiny object
var whatIWant = undefined || "well defined"; // is "well defined"
var whatIWant = 0 || 42; // is 42
var whatIWant = "" || "a million bucks"; // is "a million bucks"
var whatIWant = "false" || "no way"; // is "false"
function coalesce() {
var len = arguments.length;
for (var i=0; i<len; i++) {
if (arguments[i] !== null && arguments[i] !== undefined) {
return arguments[i];
}
}
return null;
}
var xyz = {};
xyz.val = coalesce(null, undefined, xyz.val, 5);
// xyz.val now contains 5
此解决方案的工作方式类似于 SQL 合并函数,它接受任意数量的参数,如果它们都没有值则返回 null。它的行为类似于 C# ?? 运算符的意义在于,“”、false 和 0 被视为 NOT NULL,因此算作实际值。如果您来自.net 背景,这将是最自然的感觉解决方案。
它看起来像这样:
x ?? y
const response = {
settings: {
nullValue: null,
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
const undefinedValue = response.settings?.undefinedValue ?? 'some other default'; // result: 'some other default'
const nullValue = response.settings?.nullValue ?? 'some other default'; // result: 'some other default'
const headerText = response.settings?.headerText ?? 'Hello, world!'; // result: ''
const animationDuration = response.settings?.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false
如果||
作为 C# 的替代品??
在您的情况下还不够好,因为它会吞下空字符串和零,您总是可以编写自己的函数:
function $N(value, ifnull) {
if (value === null || value === undefined)
return ifnull;
return value;
}
var whatIWant = $N(someString, 'Cookies!');
在这里没有人提到 的潜力NaN
,这对我来说也是一个空值。所以,我想我会加上我的两分钱。
对于给定的代码:
var a,
b = null,
c = parseInt('Not a number'),
d = 0,
e = '',
f = 1
;
如果您要使用||
运算符,您将获得第一个非 false 值:
var result = a || b || c || d || e || f; // result === 1
如果您使用新的??
(空合并)运算符,您将得到c
,它具有以下值:NaN
vas result = a ?? b ?? c ?? d ?? e ?? f; // result === NaN
这些对我来说似乎都不对。在我自己的合并逻辑小世界中,可能与您的世界不同,我认为 undefined、null 和 NaN 都是“null-ish”。所以,我希望d
从合并方法中恢复(零)。
如果任何人的大脑都像我一样工作,并且您想排除NaN
,那么这个自定义coalesce
方法(与此处发布的不同)将完成:
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;
}
对于那些希望代码尽可能短并且不介意有点不清晰的人,您也可以按照@impinball 的建议使用它。这利用了 NaN 永远不等于 NaN 的事实。你可以在这里阅读更多内容:为什么 NaN 不等于 NaN?
function coalesce() {
var i, arg;
for( i=0; i < arguments.length; i++ ) {
arg = arguments[i];
if( arg != null && arg === arg ) { //arg === arg is false for NaN
return arg;
}
}
return null;
}
目前正在向浏览器中添加一个新的运算符,??=
. 这将空合并运算符??
与赋值运算符结合在一起=
。
注意:这在公共浏览器版本中还不常见。将随着可用性的变化而更新。
??=
检查变量是否未定义或为空,如果已定义则短路。如果不是,则将右侧的值分配给变量。
let a // undefined
let b = null
let c = false
a ??= true // true
b ??= true // true
c ??= true // false
let x = ["foo"]
let y = { foo: "fizz" }
x[0] ??= "bar" // "foo"
x[1] ??= "bar" // "bar"
y.foo ??= "buzz" // "fizz"
y.bar ??= "buzz" // "buzz"
x // Array [ "foo", "bar" ]
y // Object { foo: "fizz", bar: "buzz" }
浏览器支持22 年 1 月 - 89%
是的,它的提案现在是第 4 阶段。这意味着该提案已准备好包含在正式的 ECMAScript 标准中。您已经可以在 Chrome、Edge 和 Firefox 的最新桌面版本中使用它,但我们将不得不等待更长时间,直到此功能达到跨浏览器稳定性。
查看以下示例以演示其行为:
// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = undefined;
const var2 = "fallback value";
const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);
前面的例子等价于:
const var1 = undefined;
const var2 = "fallback value";
const result = (var1 !== null && var1 !== undefined) ?
var1 :
var2;
console.log(`Nullish coalescing results in: ${result}`);
请注意,无效合并不会像操作员那样威胁虚假值||
(它只检查undefined
ornull
值),因此以下代码段将按如下方式运行:
// note: this will work only if you're running latest versions of aforementioned browsers
const var1 = ""; // empty string
const var2 = "fallback value";
const result = var1 ?? var2;
console.log(`Nullish coalescing results in: ${result}`);
对于 TypesScript 用户,从TypeScript 3.7开始,此功能现在也可用。
阅读您的说明后,@Ates Goral 的回答提供了如何在 JavaScript 中执行您在 C# 中执行的相同操作。
@Gumbo 的答案提供了检查 null 的最佳方法;但是,重要的是要注意==
与===
JavaScript中的区别,尤其是在检查undefined
和/或null
.
这里有一篇关于两个术语差异的非常好的文章。基本上,了解如果您使用==
而不是===
,JavaScript 将尝试合并您正在比较的值并返回合并后的比较结果。
请注意 JavaScript 特定的 null 定义。javascript中有两个“无价值”的定义。1. Null:当一个变量为null时,表示它里面没有数据,但是这个变量已经在代码中定义了。像这样:
var myEmptyValue = 1;
myEmptyValue = null;
if ( myEmptyValue === null ) { window.alert('it is null'); }
// alerts
在这种情况下,变量的类型实际上是 Object。测试它。
window.alert(typeof myEmptyValue); // prints Object
未定义:当一个变量之前没有在代码中定义时,正如预期的那样,它不包含任何值。像这样:
if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); }
// alerts
如果是这种情况,您的变量的类型是“未定义”。
请注意,如果您使用类型转换比较运算符 (==),JavaScript 将对这两个空值执行相同的操作。要区分它们,请始终使用类型严格的比较运算符 (===)。
请注意,React 的工具链从版本 3.3.0(发布 5.12.2019)create-react-app
开始支持空合并。从发行说明:
可选链接和空值合并运算符
我们现在支持可选的链接和无效合并运算符!
// Optional chaining a?.(); // undefined if `a` is null/undefined b?.c; // undefined if `b` is null/undefined // Nullish coalescing undefined ?? 'some other default'; // result: 'some other default' null ?? 'some other default'; // result: 'some other default' '' ?? 'some other default'; // result: '' 0 ?? 300; // result: 0 false ?? true; // result: false
这就是说,如果您使用create-react-app
3.3.0+,您今天就可以在您的 React 应用程序中开始使用 null-coalesce 运算符。
??
对比||
对比&&
其他答案都没有比较所有这三个。由于贾斯汀·约翰逊(Justin Johnson)的评论获得了如此多的选票,并且由于JavaScript 中的双问号与 &&&&
被标记为与此相同,因此将其包含在答案中是有意义的。
首先是受贾斯汀约翰逊评论的启发:
||
返回第一个“truey”值,否则返回最后一个值。
&&
返回第一个“假”值,否则返回最后一个值。
??
返回第一个非空、非未定义的值,否则返回最后一个值,无论它是什么。
然后,在实时代码中演示:
let F1,
F2 = null,
F3 = 0,
F4 = '',
F5 = parseInt('Not a number (NaN)'),
T1 = 3,
T2 = 8
console.log( F1 || F2 || F3 || F4 || F5 || T1 || T2 ) // 3 (T1)
console.log( F1 || F2 || F3 || F4 || F5 ) // NaN (F5)
console.log( T1 && T2 && F1 && F2 && F3 && F4 && F5 ) // undefined (F1)
console.log( T1 && T2 ) // 8 (T2)
console.log( F1 ?? F2 ?? F3 ?? F4 ?? F5 ?? T1 ) // 0 (F3)
console.log( F1 ?? F2) // null (F2)
它有望很快在 Javascript 中可用,因为它在 2020 年 4 月处于提案阶段。您可以在此处监控状态以获取兼容性和支持 - https://developer.mozilla.org/en-US/docs/Web/ JavaScript/参考/运算符/Nullish_coalescing_operator
对于使用 Typescript 的人,您可以使用Typescript 3.7中的空值合并运算符
从文档 -
您可以将此功能(运算符)视为在处理or
??
时“回退”到默认值的一种方式。当我们编写类似的代码时null
undefined
let x = foo ?? bar();
这是一种新的说法,即
foo
当它“存在”时将使用该值;但是当它是null
or时undefined
,计算bar()
它的位置。
需要支持旧浏览器并具有对象层次结构
body.head.eyes[0] //body, head, eyes may be null
可以用这个,
(((body||{}) .head||{}) .eyes||[])[0] ||'left eye'
话太多,这里有两个项目:
常量 foo = '' || '默认字符串';
控制台.log(foo); // 输出是'默认字符串'
常量 foo = '' ?? '默认字符串';
控制台.log(foo); // 输出为空字符串,即 ''
空值合并运算符 (??) 是一个逻辑运算符,当其左侧操作数为空或未定义时返回其右侧操作数,否则返回其左侧操作数。
现在它已全面支持最新版本的主流浏览器,如 Chrome、Edge、Firefox、Safari 等。这里是 null 运算符和 Nullish Coalescing 运算符之间的比较
const response = {
settings: {
nullValue: null,
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
/* OR Operator */
const undefinedValue = response.settings.undefinedValue || 'Default Value'; // 'Default Value'
const nullValue = response.settings.nullValue || 'Default Value'; // 'Default Value'
const headerText = response.settings.headerText || 'Hello, world!'; // 'Hello, world!'
const animationDuration = response.settings.animationDuration || 300; // 300
const showSplashScreen = response.settings.showSplashScreen || true; // true
/* Nullish Coalescing Operator */
const undefinedValue = response.settings.undefinedValue ?? 'Default Value'; // 'Default Value'
const nullValue = response.settings.nullValue ?? ''Default Value'; // 'Default Value'
const headerText = response.settings.headerText ?? 'Hello, world!'; // ''
const animationDuration = response.settings.animationDuration ?? 300; // 0
const showSplashScreen = response.settings.showSplashScreen ?? true; // false
使用 Babel 的人需要升级到最新版本才能使用无效合并 (??):
Babel 7.8.0 默认支持新的 ECMAScript 2020 功能:您不再需要使用预设环境为无效合并 (??)、可选链接 (?.) 和动态 import() 启用单个插件
ECMAScript 2021启用了两个新功能:
let b = undefined ?? 5;
console.log(b); // 5
const car = {speed : 20};
car.speed ??= 5;
console.log(car.speed);
car.name ??= "reno";
console.log(car.name);
有关逻辑无效分配的更多信息,请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment
可以在此处找到有关 Nullish 合并运算符的更多信息 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator