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

Is there a “null coalescing” operator in JavaScript?

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

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

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

我能为javascript找到的最佳近似值是使用条件运算符:

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

有点恶心。我能做得更好吗?


与c空合并运算符(??等效的javascript使用逻辑或(||时):

1
var whatIWant = someString ||"Cookies!";

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

澄清

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

1
2
3
4
5
alert(Boolean(null)); // false
alert(Boolean(undefined)); // false
alert(Boolean(0)); // false
alert(Boolean("")); // false
alert(Boolean("false")); // true -- gotcha! :)

这意味着:

1
2
3
4
5
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
2
3
4
5
6
7
8
9
10
11
12
13
14
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合并函数类似,它接受任意数量的参数,如果这些参数都没有值,则返回空值。它的行为就像C??运算符,即"、false和0被视为不为空,因此计为实际值。如果你来自.NET背景,这将是最自然的感觉解决方案。


如果用||代替c的??在您的情况下不够好,因为它吞下空字符串和零,您可以始终编写自己的函数:

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!');


是的,很快就要到了。请参阅此处的建议和此处的实施状态。

看起来是这样的:

1
x ?? y

例子

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'; // 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

这里没有人提到过NaN的潜力,对我来说,它也是一个空值。所以,我想加上我的两分钱。

对于给定代码:

1
2
3
4
5
6
7
var a,
    b = null,
    c = parseInt('Not a number'),
    d = 0,
    e = '',
    f = 1
;

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

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

如果您使用典型的合并方法,如本文所述,您将得到c,其值为:NaN

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

我觉得这两个都不对。在我自己的合并逻辑的小世界里,可能不同于你的世界,我认为未定义、空和NaN都是"空的"。所以,我希望从coalesce方法中得到==

如果任何人的大脑像我的一样工作,而你想排除NaN,那么这种方法将实现:

1
2
3
4
5
6
7
8
9
10
11
12
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。你可以在这里读到更多:为什么南不等于南?

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 === arg ) { //arg === arg is false for NaN
            return arg;
        }
    }
    return null;
}


目前没有支持,但JS标准化过程正在进行中:https://github.com/tc39/proposal-optional-chaining


注意javascript特定的空定义。在javascript中有两个"无值"的定义。1。空:当变量为空时,意味着它不包含任何数据,但该变量已在代码中定义。这样地:

1
2
3
4
var myEmptyValue = 1;
myEmptyValue = null;
if ( myEmptyValue === null ) { window.alert('it is null'); }
// alerts

在这种情况下,变量的类型实际上是对象。测试它。

1
window.alert(typeof myEmptyValue); // prints Object
  • 未定义:如果代码中以前没有定义变量,如预期的那样,它不包含任何值。这样地:

    1
    2
    if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); }
    // alerts
  • 如果出现这种情况,则变量的类型为"未定义"。

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


    在阅读了您的说明之后,@ates goral的答案提供了如何在JavaScript的C中执行相同的操作。

    @gumbo的答案提供了检查空值的最佳方法;但是,重要的是要注意在javascript中=====的区别,特别是在检查undefined和/或null的问题上。

    这里有一篇关于这两个术语之间差别的好文章。基本上,要理解,如果使用==而不是===,javascript将尝试合并要比较的值,并返回合并后的比较结果。