JavaScript中是否有“null coalescing”运算符?

时间:2009-01-24 18:18:03

标签: javascript operators null-coalescing-operator null-coalescing

Javascript中是否存在空合并运算符?

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

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

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

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

这是一种icky icky恕我直言。我能做得更好吗?

19 个答案:

答案 0 :(得分:1833)

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

var whatIWant = someString || "Cookies!";

有些情况(下面说明)表明行为与C#的行为不匹配,但这是在JavaScript中分配默认/替代值的一般简洁方法。


澄清

无论第一个操作数的类型如何,如果将其转换为布尔结果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"

答案 1 :(得分:64)

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 coalesce函数,它接受任意数量的参数,如果它们都没有值,则返回null。它的行为就像C#??运算符,“”,false和0被认为是NOT NULL,因此计为实际值。如果你来自.net背景,这将是最自然的解决方案。

答案 2 :(得分:43)

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

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

 var whatIWant = $N(someString, 'Cookies!');

答案 3 :(得分:19)

是的,它即将推出。请参阅proposal hereimplementation status here

看起来像这样:

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

答案 4 :(得分:12)

在这里没有人提到NaN的潜力,对我而言,这也是一个零值。所以,我以为我会增加两美分。

对于给定的代码:

var a,
    b = null,
    c = parseInt('Not a number'),
    d = 0,
    e = '',
    f = 1
;

如果您使用||运算符,则会获得第一个非假值:

var result = a || b || c || d || e || f; // result === 1

如果您使用典型的合并方法as posted here,则会获得c,其值为:NaN

var result = coalesce(a,b,c,d,e,f); // result.toString() === 'NaN'

其中似乎对我不对。在我自己的小合并逻辑世界中,可能与你的世界不同,我认为undefined,null和NaN都是“null-ish”。所以,我希望从合并方法中获得d(零)。

如果有人的大脑像我一样工作,而你想要排除NaN,那么这种方法就可以实现这一点:

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的事实。您可以在此处详细了解:Why is NaN not equal to 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;
}

答案 5 :(得分:7)

目前没有支持,但JS标准化流程正在开展工作:https://github.com/tc39/proposal-optional-chaining

答案 6 :(得分:5)

是的,它的proposal现在是Stage 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}`);

请注意,虚假合并不会威胁虚假重视||运算符的操作方式(它仅检查{{ 1}}或undefined值),因此以下代码段的作用如下:

null


对于TypesScript用户,从TypeScript 3.7开始,该功能现在也可用。

答案 7 :(得分:4)

要小心null的JavaScript特定定义。 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
    
  2. 如果是这种情况,变量的类型是'undefined'。

    请注意,如果使用类型转换比较运算符(==),JavaScript将同时对这两个空值起作用。为了区分它们,总是使用类型严格比较运算符(===)。

答案 8 :(得分:3)

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

@Gumbo的答案提供了检查null的最佳方法;但是,在检查==和/或{{1}的问题时,请务必注意JavaScript 中的===undefined之间的差异,尤其是 }。

关于两个术语here的区别,有一篇非常好的文章。基本上,要明白如果您使用null而不是==,JavaScript会尝试合并您正在比较的值,并在此合并之后返回比较的结果。

答案 9 :(得分:2)

请注意,自version 3.3.0 (released 5.12.2019)以来,React的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运算符。

答案 10 :(得分:2)

该版本有望在2020年4月的提案阶段以Javascript的形式提供。您可以在此处监视其状态以获得兼容性和支持-https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

对于使用打字稿的人,您可以使用nullish coalescing operator中的Typescript 3.7

从文档中-

您可以将??运算符这一功能视为“跌倒”的一种方式 nullundefined时返回默认值。什么时候我们 像这样写代码

let x = foo ?? bar();

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

答案 11 :(得分:2)

逻辑无效分配,2020年以上的解决方案

当前正在将新的运算符添加到浏览器??=。这会将空合并运算符??与赋值运算符=组合在一起。

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

??=检查变量是否未定义或为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" }

Browser Support 2020年9月-3.7%

Mozilla Documentation

答案 12 :(得分:1)

是的,有。它称为@babel/plugin-proposal-optional-chaining 在这里查看我的详细答案:https://stackoverflow.com/a/54482814/5506730

答案 13 :(得分:1)

废话太多,这里有两点:

  1. 逻辑或

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

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

  1. 空合并运算符

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

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

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

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

答案 14 :(得分:1)

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

const asValid = <T extends {}>( record: T & ValidateRecord<T> ): ValidateRecord<T> => record;

可以使用它,


const goodObj = {
  Jason: {
    firstName: "Jason"
  },
  Tim: {
    firstName: "Tim"
  }
} as const;

// should be ok
const myRecordGood = asValid(goodObj);

// should be a person with {firstName: "Tim"}
const A = myRecordGood["Tim"]

// should be a problem
const B = myRecordGood["Missing"]

const badObj = {
  Jason: {
    firstName: "Bob"
  },
  Tim: {
    firstName: "John"
  }
} as const;

// should be a problem
const myRecordBad = asValid(badObj);

答案 15 :(得分:1)

JS现在得到一个空合并运算符! 是的,目前正在第三阶段进入第四阶段。 https://github.com/tc39/proposal-nullish-coalescing

提案示例:

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

答案 16 :(得分:0)

现在,它在主要版本的主流浏览器(例如Chrome,Edge,Firefox,Safari等)的最新版本中提供全面支持。这是null运算符和Nullish合并运算符之间的比较

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

答案 17 :(得分:0)

确定正确的答案

它是否存在于JavaScript中? 是的。 BUT。 Stage 3上> 2020-02-06 ,目前尚不支持。 点击下面URL中的链接,然后转到“规格”和“浏览器兼容性”标题,以获取有关其位置的更多信息。

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

无效的合并运算符(??)是一个逻辑运算符, 当其左侧操作数为时,返回其右侧操作数 null或undefined,否则返回其左侧操作数。

与逻辑OR(||)运算符相反,返回左操作数 如果它是不为null或未定义的虚假值。换一种说法, 如果使用||为另一个变量foo提供一些默认值, 如果您认为某些虚假行为,可能会遇到意想不到的行为 可用的值(例如“''或0)。有关更多示例,请参见下面。

想要示例吗?跟随我发布的链接,它包含了所有内容。

答案 18 :(得分:0)

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

<块引用>

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

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