Существует ли в JavaScript оператор “null coalescing”?
-
20-08-2019 - |
Вопрос
Существует ли оператор объединения null в Javascript?
Например, в C # я могу сделать это:
String someString = null;
var whatIWant = someString ?? "Cookies!";
Наилучшее приближение, которое я могу найти для Javascript, - это использование условного оператора:
var someString = null;
var whatIWant = someString ? someString : 'Cookies!';
Что, ИМХО, довольно мерзко.Могу ли я сделать лучше?
Решение
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!');
Да, это скоро произойдет.Видишь предложение здесь и статус реализации здесь.
Это выглядит примерно так:
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
Никто не упомянул здесь о потенциале для 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
Если вы используете типичный метод коалесцирования, как опубликовано здесь, вы получите c
, который имеет значение: NaN
var result = coalesce(a,b,c,d,e,f); // result.toString() === 'NaN'
Ни то , ни другое некоторые из них кажутся мне правильными.В моем собственном маленьком мире логики объединения, который может отличаться от вашего мира, я считаю undefined, null и 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
остерегайтесь специфичного для JavaScript определения null.в javascript существует два определения термина "нет значения".1.Ноль:когда переменной присвоено значение null, это означает, что в ней нет данных, но переменная уже определена в коде.вот так:
var myEmptyValue = 1;
myEmptyValue = null;
if ( myEmptyValue === null ) { window.alert('it is null'); }
// alerts
в таком случае тип вашей переменной на самом деле является Object .проверьте это.
window.alert(typeof myEmptyValue); // prints Object
Неопределенный:когда переменная ранее не была определена в коде, и, как ожидалось, она не содержит никакого значения.вот так:
if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); } // alerts
в таком случае тип вашей переменной 'undefined'.
обратите внимание, что если вы используете оператор сравнения преобразования типов (==), JavaScript будет действовать одинаково для обоих этих пустых значений.чтобы различать их, всегда используйте оператор сравнения со строгим типом (===).
Прочитав ваше разъяснение, в ответе @Ates Goral объясняется, как выполнить ту же операцию, которую вы выполняете на C #, в JavaScript.
Ответ @Gumbo's предоставляет лучший способ проверить наличие null;однако важно отметить разницу в ==
против ===
в JavaScript особенно когда дело доходит до вопросов проверки на undefined
и/или null
.
Есть действительно хорошая статья о разнице в двух терминах здесь.В принципе, поймите, что если вы используете ==
вместо того , чтобы ===
, JavaScript попытается объединить значения, которые вы сравниваете, и вернет результат сравнения после это слияние.
JS теперь получает нулевой объединяющий оператор!В настоящее время на стадии-3 переходим к Стадии-4, ура!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