1514

Javascript中是否有空合并运算符?

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

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

我可以为 Javascript 找出的最佳近似值是使用条件运算符:

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

恕我直言,这有点恶心。我能做得更好吗?

4

17 回答 17

2272

更新

JavaScript 现在支持空值合并运算符 (??)。当其左侧操作数为nullor时返回其右侧操作数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"
于 2009-01-24T18:25:31.133 回答
81
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 背景,这将是最自然的感觉解决方案。

于 2014-03-08T05:24:46.097 回答
73

是的,它很快就会到来。请参阅此处的提案和此处实施状态

它看起来像这样:

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
于 2018-05-07T09:32:28.760 回答
46

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

 function $N(value, ifnull) {
    if (value === null || value === undefined)
      return ifnull;
    return value;
 }

 var whatIWant = $N(someString, 'Cookies!');
于 2009-01-24T18:45:42.230 回答
17

在这里没有人提到 的潜力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;
}
于 2015-05-26T21:07:50.550 回答
7

逻辑无效分配,2020+ 解决方案

目前正在向浏览器中添加一个新的运算符,??=. 这将空合并运算符??与赋值运算符结合在一起=

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

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

基本示例

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%

Mozilla 文档

于 2020-07-09T22:00:47.703 回答
6

是的,它的提案现在是第 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}`);

请注意,无效合并不会像操作员那样威胁虚假||(它只检查undefinedornull值),因此以下代码段将按如下方式运行:

// 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开始,此功能现在也可用。

于 2020-03-26T18:56:24.660 回答
5

阅读您的说明后,@Ates Goral 的回答提供了如何在 JavaScript 中执行您在 C# 中执行的相同操作。

@Gumbo 的答案提供了检查 null 的最佳方法;但是,重要的是要注意=====JavaScript中的区别,尤其是在检查undefined和/或null.

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

于 2009-01-24T18:23:21.900 回答
5

请注意 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
    

如果是这种情况,您的变量的类型是“未定义”。

请注意,如果您使用类型转换比较运算符 (==),JavaScript 将对这两个空值执行相同的操作。要区分它们,请始终使用类型严格的比较运算符 (===)。

于 2009-01-24T18:35:39.287 回答
4

请注意,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-app3.3.0+,您今天就可以在您的 React 应用程序中开始使用 null-coalesce 运算符。

于 2019-12-05T12:42:51.200 回答
3

??对比||对比&&

其他答案都没有比较所有这三个。由于贾斯汀·约翰逊(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)

于 2021-11-28T12:00:07.290 回答
2

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

对于使用 Typescript 的人,您可以使用Typescript 3.7中的空值合并运算符

从文档 -

您可以将此功能(运算符)视为在处理or??时“回退”到默认值的一种方式。当我们编写类似的代码时nullundefined

let x = foo ?? bar();

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

于 2020-01-13T16:19:44.827 回答
1

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

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

可以用这个,

(((body||{}) .head||{}) .eyes||[])[0] ||'left eye'
于 2020-09-29T22:18:09.250 回答
1

话太多,这里有两个项目:

  1. 逻辑或

常量 foo = '' || '默认字符串';

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

  1. 空值合并运算符

常量 foo = '' ?? '默认字符串';

控制台.log(foo); // 输出为空字符串,即 ''

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

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

于 2021-02-15T05:52:36.903 回答
0

现在它已全面支持最新版本的主流浏览器,如 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
于 2020-04-08T10:54:43.423 回答
0

使用 Babel 的人需要升级到最新版本才能使用无效合并 (??):

Babel 7.8.0 默认支持新的 ECMAScript 2020 功能:您不再需要使用预设环境为无效合并 (??)、可选链接 (?.) 和动态 import() 启用单个插件

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

于 2021-06-05T01:39:42.170 回答
0

ECMAScript 2021启用了两个新功能:

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

let b = undefined ?? 5;

console.log(b); // 5

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

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

于 2021-10-11T11:03:21.643 回答