JavaScript中是否有“空合并”运算符?

JavaScript中是否有null合并运算符?

例如,在C#中,我可以这样做:

String someString = null;var whatIWant = someString ?? "Cookies!";

我能为Javascript找到的最好的近似是使用条件运算符:

var someString = null;var whatIWant = someString ? someString : 'Cookies!';

恕我直言。我能做得更好吗?

448391 次浏览

在阅读了您的澄清之后,@Ates Gonal的回答提供了如何在JavaScript中执行与您在C#中执行的相同操作。

@Gumbo的回答提供了检查null的最佳方法;然而,重要的是要注意JavaScript特别是=====的区别,当涉及到检查undefined和/或null的问题时。

有一篇关于两个术语这里差异的非常好的文章。基本上,请理解,如果您使用==而不是===,JavaScript将尝试合并您正在比较的值并返回比较结果之后这种合并。

更新

JavaScript现在支持零合并算子(??)。当其左侧操作数为nullundefined时,它返回其右侧操作数,否则返回其左侧操作数。

旧答案

使用前请检查兼容性。


与C#null合并运算符(??)等效的JavaScript使用逻辑OR(||):

var whatIWant = someString || "Cookies!";

在某些情况下(下面澄清),行为与C#的行为不匹配,但这是在JavaScript中分配默认/替代值的一般、简洁的方式。


澄清

无论第一个操作数的类型如何,如果将其转换为布尔值导致false,则赋值将使用第二个操作数。注意以下所有情况:

alert(Boolean(null)); // falsealert(Boolean(undefined)); // falsealert(Boolean(0)); // falsealert(Boolean("")); // falsealert(Boolean("false")); // true -- gotcha! :)

这意味着:

var whatIWant = null || new ShinyObject(); // is a new shiny objectvar whatIWant = undefined || "well defined"; // is "well defined"var whatIWant = 0 || 42; // is 42var whatIWant = "" || "a million bucks"; // is "a million bucks"var whatIWant = "false" || "no way"; // is "false"

注意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
  1. 未定义:当一个变量在代码中之前没有定义,并且如预期的那样,它不包含任何值。像这样:

    if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); }// alerts

if such case, the type of your variable is 'undefined'.

notice that if you use the type-converting comparison operator (==), JavaScript will act equally for both of these empty-values. to distinguish between them, always use the type-strict comparison operator (===).

如果||作为C#的??的替代品在您的情况下不够好,因为它吞下了空字符串和零,您可以随时编写自己的函数:

 function $N(value, ifnull) {if (value === null || value === undefined)return ifnull;return value;}
var whatIWant = $N(someString, 'Cookies!');
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

此解决方案的工作方式类似于SQLcoalesce函数,它接受任意数量的参数,如果它们都没有值,则返回null。它的行为类似于C#??运算符,因为“”、false和0被认为不是NULL,因此算作实际值。如果你来自. net背景,这将是最自然的感觉解决方案。

这里没有人提到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

其中都不是对我来说似乎是正确的。在我自己的合并逻辑的小世界中,可能与你们的世界不同,我认为未定义、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 NaNreturn arg;}}return null;}

是的,它即将到来。见这里的提案这里的执行状态

它看起来像这样:

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: 0const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false

请注意,React的create-react-app工具链支持自版本3.3.0(发布5.12.2019)以来的空合并。来自发行说明:

可选的链式和零合并运算符

我们现在支持可选的链接和空合并运算符!

// Optional chaininga?.(); // undefined if `a` is null/undefinedb?.c; // undefined if `b` is null/undefined
// Nullish coalescingundefined ?? 'some other default'; // result: 'some other default'null ?? 'some other default'; // result: 'some other default''' ?? 'some other default'; // result: ''0 ?? 300; // result: 0false ?? true; // result: false

也就是说,如果您使用create-react-app 3.3.0+,您可以从今天开始在您的React应用程序中使用null-coalesce运算符。

它有望很快在Javascript中可用,因为它自2020年4月起处于提案阶段。您可以在此处监控状态以获取兼容性和支持-https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

对于使用TypeScript的人,您可以使用打字稿3.7中的零合并算子

从文档-

您可以将此功能-??运算符-视为“下降”的一种方式在处理nullundefined时返回"到默认值。当我们编写类似

的代码

let x = foo ?? bar();

这是一种新的说法,表示值foo将在“存在”时使用;但是当它是nullundefined时,计算bar()的位置。

是的,它的提案现在是阶段4。这意味着该提案已准备好包含在正式的ECMAScript标准中。您已经可以在最近的桌面版本的Chrome、Edge和Firefox中使用它,但我们将不得不等待更长的时间,直到该功能达到跨浏览器的稳定性。

查看以下示例以演示其行为:

// note: this will work only if you're running latest versions of aforementioned browsersconst 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}`);

请注意,零结合力没有威胁Falsy的值设置为||操作符所做的方式(它只检查undefinednull值),因此以下代码段将如下所示:

// note: this will work only if you're running latest versions of aforementioned browsersconst var1 = ""; // empty stringconst var2 = "fallback value";
const result = var1 ?? var2;console.log(`Nullish coalescing results in: ${result}`);


对于Types Script用户,从TypeScript 3.7开始,此功能现在也可用。

现在它完全支持最新版本的主要浏览器,如Chrome,Edge,Firefox,Safari等

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; //  300const 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; // 0const showSplashScreen = response.settings.showSplashScreen ?? true; //  false

逻辑为空赋值,2020+方案

当前正在向浏览器添加一个新的运算符??=。这将空合并运算符??与赋值操作符=相结合。

注意:这在公共浏览器版本中并不常见。将随着可用性的变化而更新。

??=检查变量是否未定义或为null,如果已定义则短路。如果不是,则将右侧值分配给变量。

基本示例

let a          // undefinedlet b = nulllet c = false
a ??= true  // trueb ??= true  // truec ??= 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" }

浏览器支持 1月22日-89%

Mozilla文档

需要支持旧浏览器并有对象层次结构

body.head.eyes[0]  //body, head, eyes  may be null

可以用这个,

(((body||{}) .head||{}) .eyes||[])[0] ||'left eye'

这里有两个项目:

  1. 逻辑或

const foo = '' || '默认字符串;

console.log(foo);//输出是'默认字符串'

  1. 零合并算子

const foo="??'默认字符串';

console.log(foo);//输出为空字符串,即"

空合并运算符(??)是一个逻辑运算符,当其左侧操作数为空或未定义时返回其右侧操作数,否则返回其左侧操作数。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

那些正在使用Babel的人,需要升级到最新版本才能使用空合并(??):

Babel 7.8.0默认支持新的ECMAScript 2020功能:您不需要启用单独的插件进行nul的合并(??),可选链接(?.)和动态导入()不再使用preset-env

https://babeljs.io/blog/2020/01/11/7.8.0

ECMAScript 2021启用了两个新功能:

  1. 零合并算子(??)是一个逻辑运算符,当其左侧操作数为空或未定义时返回其右侧操作数,否则返回其左侧操作数。

let b = undefined ?? 5;
console.log(b); // 5

  1. 逻辑零赋值(x??=y)运算符,仅在x具有空值(null或未定义)时分配。

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

可以在这里找到更多关于Nul的合并运算符https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

?? vs|| vs&&

因为贾斯汀·约翰逊的评论有这么多的选票,而且JavaScript中的双问号vs&&被标记为这个的重复,所以在答案中包含&&是有意义的。

第一个字,灵感来自贾斯汀·约翰逊的评论:

  • ||返回第一个“truey”值,否则返回最后一个值,无论它是什么。

  • &&返回第一个“false sey”值,否则返回最后一个值,无论它是什么。

  • ??返回第一个非空、非未定义的值,否则返回最后一个值,无论它是什么。

然后,在实时代码中演示:

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)