Есть ли оператор "null coalescing" в JavaScript?

есть ли оператор объединения null в Javascript?

например, в C#, я могу сделать это:

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

лучшее приближение, которое я могу понять для Javascript, - это использование условного оператора:

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

который является своего рода icky IMHO. Могу я сделать лучше?

8 ответов


эквивалент JavaScript оператора коалесцирования c# null (??) использует логическое или (||):

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"

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 считаются не нулевыми и поэтому считаются фактическими значениями. Если вы пришли из .net-фона, это будет самое естественное решение для чувств.


Если || в качестве замены C# ' S ?? недостаточно хорошо в вашем случае, потому что он глотает пустые строки и нули, вы всегда можете написать свою собственную функцию:

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

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

никто не упомянул здесь потенциал NaN, который--для меня--также является нулевым значением. Так что я решил добавить свои два цента.

для данного кода:

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

если бы вы использовали || оператор, вы получаете первое значение non-false:

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

если вы используете типичный метод объединения,как написал здесь, вы c, который имеет значение: NaN

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

ни из них мне кажется правильным. В моем собственном маленьком мире логики слияния, который может отличаться от вашего мира, я рассматриваю неопределенное, нулевое и NaN как все "нулевое". Итак, я ожидал бы вернуться 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. Вы можете прочитать больше об этом здесь: почему 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;
}

Да, это скоро. См.


В настоящее время нет поддержки, но процесс стандартизации JS работает над этим:https://github.com/tc39/proposal-optional-chaining


остерегайтесь определения null в JavaScript. в javascript существует два определения "нет значения". 1. Null: когда переменная имеет значение null, это означает, что она не содержит данных, но переменная уже определена в коде. вот так:

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

в таком случае тип переменной-это на самом деле объект. проверить его.

window.alert(typeof myEmptyValue); // prints Object
  1. Undefined: когда переменная не была определена ранее в коде и, как ожидалось, она не содержит любое значение. вот так:

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

если такой случай, тип вашей переменной "undefined".

обратите внимание, что если вы используете оператор сравнения преобразования типов ( = = ), JavaScript будет действовать одинаково для обоих этих пустых значений. чтобы различать их, всегда используйте тип-строгий оператор сравнения (===).


после прочтения вашего разъяснения, ответ @Ates Goral предоставляет, как выполнить ту же операцию, которую вы делаете в C# в JavaScript.

@Гамбо обеспечивает лучший способ проверить на null; однако, важно отметить разницу в == и === в JavaScript особенно когда дело доходит до вопросов проверки undefined и/или null.

есть действительно хорошая статья о разнице в двух терминах здесь. В принципе, поймите, что если вы используете == вместо ===, JavaScript попытается объединить значения, которые вы сравниваете, и вернуть результат сравнения после этот коалесценции.