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

Существует ли в Javascript нулевой оператор коалесцирования?

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

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

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

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

Какая-то нехорошая ИМХО. Могу ли я лучше?

972
задан Daniel Schaffer 24 янв. '09 в 21:18
источник поделиться
8 ответов

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

var whatIWant = someString || "Cookies!";

Есть случаи (пояснено ниже), что поведение не будет соответствовать поведению С#, но это общий, точный способ присвоения значений по умолчанию/альтернативных значений в 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"
1574
ответ дан Ates Goral 24 янв. '09 в 21:25
источник поделиться
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, если ни одно из них не имеет значения. Он ведет себя как С#? оператора в том смысле, что "", false и 0 считаются NOT NULL и поэтому считаются фактическими значениями. Если вы пришли из фона .net, это будет наиболее естественное решение.

56
ответ дан Brent Larsen 08 марта '14 в 8:24
источник поделиться

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

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

 var whatIWant = $N(someString, 'Cookies!');
38
ответ дан sth 24 янв. '09 в 21:45
источник поделиться

Никто не упомянул здесь потенциал для 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

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

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

Ни то, ни другое из них не кажется мне правильным. В моем собственном маленьком мире логики coalesce, которая может отличаться от вашего мира, я рассматриваю undefined, null и NaN, поскольку все они являются "нуль-иш". Итак, я ожидал бы вернуть d (ноль) из метода coalesce.

Если какой-либо мозг работает как мой, и вы хотите исключить 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;
}
10
ответ дан Kevin Nelson 27 мая '15 в 0:07
источник поделиться

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

6
ответ дан Elmar Jansen 17 июля '17 в 0:17
источник поделиться

Да, это скоро. См. Здесь предложение и статус реализации.

Это выглядит так:

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
5
ответ дан vaughan 07 мая '18 в 12:32
источник поделиться

остерегайтесь специфического определения null для JavaScript. в javascript есть два определения "no value". 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. Undefined: когда переменная не была определена ранее в коде и, как и ожидалось, она не содержит никакого значения. например:

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

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

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

4
ответ дан farzad 24 янв. '09 в 21:35
источник поделиться

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

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

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

3
ответ дан Tom 24 янв. '09 в 21:23
источник поделиться

Другие вопросы по меткам