Is there a "null coalescing" operator in JavaScript?

434,858

Solution 1

Update

JavaScript now supports the nullish coalescing operator (??). It returns its right-hand-side operand when its left-hand-side operand is null or undefined, and otherwise returns its left-hand-side operand.

Old Answer

Please check compatibility before using it.


The JavaScript equivalent of the C# null coalescing operator (??) is using a logical OR (||):

var whatIWant = someString || "Cookies!";

There are cases (clarified below) that the behaviour won't match that of C#, but this is the general, terse way of assigning default/alternative values in JavaScript.


Clarification

Regardless of the type of the first operand, if casting it to a Boolean results in false, the assignment will use the second operand. Beware of all the cases below:

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

This means:

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"

Solution 2

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

this solution works like the SQL coalesce function, it accepts any number of arguments, and returns null if none of them have a value. It behaves like the C# ?? operator in the sense that "", false, and 0 are considered NOT NULL and therefore count as actual values. If you come from a .net background, this will be the most natural feeling solution.

Solution 3

Yes, it is coming soon. See proposal here and implementation status here.

It looks like this:

x ?? y

Example

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

Solution 4

If || as a replacement of C#'s ?? isn't good enough in your case, because it swallows empty strings and zeros, you can always write your own function:

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

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

Solution 5

Nobody has mentioned in here the potential for NaN, which--to me--is also a null-ish value. So, I thought I'd add my two-cents.

For the given code:

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

If you were to use the || operator, you get the first non-false value:

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

If you use the new ?? (null coalescing) operator, you will get c, which has the value: NaN

vas result = a ?? b ?? c ?? d ?? e ?? f; // result === NaN

Neither of these seem right to me. In my own little world of coalesce logic, which may differ from your world, I consider undefined, null, and NaN as all being "null-ish". So, I would expect to get back d (zero) from the coalesce method.

If anyone's brain works like mine, and you want to exclude NaN, then this custom coalesce method (unlike the one posted here) will accomplish that:

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;
}

For those who want the code as short as possible, and don't mind a little lack of clarity, you can also use this as suggested by @impinball. This takes advantage of the fact that NaN is never equal to NaN. You can read up more on that here: 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;
}
Share:
434,858
Daniel Schaffer
Author by

Daniel Schaffer

Updated on January 16, 2022

Comments

  • Daniel Schaffer
    Daniel Schaffer over 2 years

    Is there a null coalescing operator in Javascript?

    For example, in C#, I can do this:

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

    The best approximation I can figure out for Javascript is using the conditional operator:

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

    Which is sorta icky IMHO. Can I do better?

    • Aprillion
      Aprillion almost 6 years
      note from 2018: x ?? y syntax is now in stage 1 proposal status - nullish coalescing
    • Jonathan Sudiaman
      Jonathan Sudiaman almost 5 years
      There is now a Babel plugin which incorporates this exact syntax.
    • Daniel Schaffer
      Daniel Schaffer almost 5 years
      Note from 2019: now is stage 3 status!
    • Daniel Schaffer
      Daniel Schaffer over 4 years
      Note from later in 2019: Nullish coalescing is available in TypeScript 3.7!
    • Kir Kanos
      Kir Kanos over 4 years
      Note from January 2020: Nullish coalescing operator is available natively in Firefox 72 but optional chaining operator is still not.
    • Mass Dot Net
      Mass Dot Net about 4 years
      The nullish coalescing operator (x ?? y) and optional chaining operator (user.address?.street) are now both Stage 4. Here's a good description about what that means: 2ality.com/2015/11/tc39-process.html#stage-4%3A-finished .
  • Ates Goral
    Ates Goral over 15 years
    Actually, null is a value. It's a special value of type Object. A variable being set to null means it contains data, the data being a reference to the null object. A variable can be defined with value undefined in your code. This is not the same as the variable not being declared.
  • Daniel Schaffer
    Daniel Schaffer over 15 years
    alert(null || '') still alerts an empty string, and I think I actually like that alert('' || 'blah') alerts blah rather than an empty string - good to know though! (+1)
  • Ates Goral
    Ates Goral over 15 years
    The actual difference between a variable being declared or not: alert(window.test)/*undefined*/; alert("test" in window)/*false*/; window.test = undefined; alert(window.test)/*undefined*/; alert("test" in window)/*true*/; for (var p in window) {/*p can be "test"*/}
  • some
    some over 15 years
    Strings like "false", "undefined", "null", "0", "empty", "deleted" are all true since they are non-empty strings.
  • Justin Johnson
    Justin Johnson over 13 years
    Of note is that || returns the first "truey" value or the last "falsey" one (if none can evaluate to true) and that && works in the opposite way: returning the last truey value or the first falsey one.
  • Bob
    Bob over 10 years
    I think I might actually prefer defining a function that returns false if (strictly) null/undefined and true otherwise - using that with a logical or; it could be more readable than many nested functions calls. e.g. $N(a) || $N(b) || $N(c) || d is more readable than $N($N($N(a, b), c), d).
  • Claudia
    Claudia almost 9 years
    Best practices - treat arguments as array-like, take advantage of NaN !== NaN (typeof + num.toString() === 'NaN' is redundant), store current argument in variable instead of arguments[i].
  • serge
    serge over 8 years
    however (a bit paradoxal) you can define a variable with the undefined value var u = undefined;
  • Haravikk
    Haravikk over 6 years
    Apologies for such a late addition, but I just wanted to note for completeness that this solution does have the caveat that it has no short-circuit evaluation; if your arguments are function calls then they will all be evaluated regardless of whether their value is returned, which differs from the behaviour of the logical OR operator, so is worth noting.
  • ToolmakerSteve
    ToolmakerSteve over 4 years
    @AtesGoral re null. While what you say is true, by convention, "null" represents "the absence of (useful) data". Hence it is considered to be "no data". And lets not forget that this is an answer to a question about "a null coalescing operator"; in this context, null is definitely treated as "no data" - regardless of how it is represented internally.
  • Gerard ONeill
    Gerard ONeill over 2 years
    This is gigantic!
  • Gerard ONeill
    Gerard ONeill over 2 years
    Before the release of the operator, this talk was necessary. But since your answer is just inferior to and much later in time than @faithful's answer, I'd argue you had too much talk.
  • Inigo
    Inigo over 2 years
    @JustinJohnson makes a good point. This answer compares all three: ?? vs || vs &&.