JavaScript установить переменную, если не определено

172

Я знаю, что могу проверить переменную javascript, а затем определить ее, если она не определена, но нет ли какого-либо способа сказать

var setVariable = localStorage.getItem ('value') || 0;

кажется намного более ясным способом, и я почти уверен, что видел это на других языках.

pedalpete
источник
30
это не тест для «неопределенного», это тест для «фальси»
Альнитак
3
Обратите внимание, что localStorage.getItem()будет возникать исключение, если пользователь отключил файлы cookie (по крайней мере, в Chrome), поэтому вы можете захотеть обернуть его внутри try...catchпредложения
urish
1
Возможная копия того, что делает конструкция х = х || значит?
Михал Перлаковский

Ответы:

304

Да, он может сделать это, но, строго говоря, он назначит значение по умолчанию, если полученное значение будет ложным , в отличие от действительно неопределенного . Было бы , следовательно , не только соответствуют , undefinedно и null, false, 0, NaN, "" (но не "0" ).

Если вы хотите установить значение по умолчанию, только если переменная строго, undefinedтогда самый безопасный способ - написать:

var x = (typeof x === 'undefined') ? your_default_value : x;

В новых браузерах на самом деле безопасно писать:

var x = (x === undefined) ? your_default_value : x;

но имейте в виду, что это можно подорвать в старых браузерах, где было разрешено объявить переменную undefinedс заданным значением, что приведет к сбою теста.

Альнитак
источник
3
Я удивлен, что этот шаблон не включен в другие JS-библиотеки.
Joemaller
Есть ли обратная сторона в использовании var x = (x === undefined ? def_val : x);как немного дольше var x = (typeof x === 'undefined') ? def_val : x;. Отличается ли поведение?
Марко Пашков
3
@marco в старых браузерах можно undefinedбыло переопределить, что привело к сбою теста на равенство.
Альнитак
@Alnitak, каков наилучший подход, чтобы использовать синтаксис, аналогичный тому, который использует OP, и все еще проверять наличие неопределенного?
Иво Перейра
@IvoPereira Вы не можете использовать ||подход в строгом тесте для неопределенного, вы должны использовать явный тест для undefinedс условным.
Альнитак
26

Ответ 2016 ES6 :

return Object.is(x, undefined) ? y : x;

Если переменная x не определена, вернуть переменную y ... в противном случае, если переменная x определена, вернуть переменную x.

Стерлинг борн
источник
4
Насколько я могу судить, Object.isне лучше, чем ===в этом случае. «Оператор === (а также оператор ==) обрабатывает числовые значения -0 и +0 как равные и рассматривает Number.NaN как не равный NaN». ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) Здесь не имеет значения.
Тревор Диксон
5
Я не согласен. Знай их обоих и используй подходящий. В частности, используйте, Object.isесли оба операнда могут быть NaN.
Тревор Диксон
2
Если Object.is () работает в 100% случаев использования, а === работает в 98% случаев использования, почему вы вообще рискуете использовать ===? Например: console.log (+0 === -0); // выводит true, а console.log (Object.is (+0, -0)); // выводит false - что лучше? Отрицательный 0 совпадает с положительным 0? Это вопрос, который вы должны задать себе, но если вы используете Object.is (), вы всегда знаете ответ. Они не одинаковы, поэтому вывод false является правильным и ожидаемым результатом.
Стерлинг Борн
2
Особый контекст здесь всегда сравнивается с undefined. Так ===будет работать 100% времени, а не только 98%. Преимущество в том, ===что его легче читать, особенно на первый взгляд, короче и позволяет избежать ненужного вызова метода. Лично я бы использовал только Object.is()тогда, когда того требует ситуация, и предпочел бы ===во всех остальных случаях.
blubberdiblub
1
Абсолютно; если вы опытный кодер Если вы случайно не забудете знак равенства, в этом случае отладка, почему == не работает где-то, я бы никогда не пожелал ни одному разработчику. Лучше быть безопасным, чем потом сожалеть, и всегда использовать Object.is (). Причина была включена в спецификацию специально для того, чтобы помочь разработчикам написать менее ошибочный код.
Стерлинг Борн
7

Мне нужно было "установить переменную, если она не определена" в нескольких местах. Я создал функцию, используя ответ @Alnitak. Надеюсь, это кому-нибудь поможет.

function setDefaultVal(value, defaultValue){
   return (value === undefined) ? defaultValue : value;
}  

Использование:

hasPoints = setDefaultVal(this.hasPoints, true);
Mcestone
источник
6

Кажется более логичным проверить typeofвместо undefined? Я предполагаю, что вы ожидаете число, когда вы устанавливаете переменную в значение 0undefined:

var getVariable = localStorage.getItem('value');
var setVariable = (typeof getVariable == 'number') ? getVariable : 0;

В этом случае, если getVariableэто не число (строка, объект, что угодно), setVariable устанавливается в0

Bruno
источник
5

ES2020 Ответ

С оператором Nullish Coalescing Operator вы можете установить значение по умолчанию, если оно valueравно нулю или не определено.

const setVariable = localStorage.getItem('value') ?? 0;

Однако вы должны знать, что пустой оператор объединения не возвращает значение по умолчанию для других типов ложных значений, таких как 0и ''.

Обратите внимание, что поддержка браузера для оператора ограничена. По данным caniuse , поддерживается только 48,34% браузеров (по состоянию на апрель 2020 года). Поддержка Node.js была добавлена ​​в версии 14 .

wentjun
источник
2

Если вы поклонник FP ( функционального программирования ), у Ramda есть полезная вспомогательная функция для этого по умолчанию defaultTo :

использование:

const result = defaultTo(30)(value)

Это более полезно при работе с undefinedлогическими значениями:

const result2 = defaultTo(false)(dashboard.someValue)

Дамиан Грин
источник
1
это точно const result = value || 30;, за исключением того, что используется промежуточная функция и +1000 байт lib
Adelin
1
@Adelin не соответствует действительности, он также обрабатывает ложные значения для логических типов. Если вы уже используете эту библиотеку (как и я), то она довольно полезна и кратка
Дамиан Грин
1

var setVariable = (typeof localStorage.getItem('value') !== 'undefined' && localStorage.getItem('value')) || 0;

Zikes
источник
Также не присвоит 0, если localStorage.getItem('value'))вернетсяfalse
Карл Адлер
1

Сегодня столкнулся с этим сценарием, где я не хотел, чтобы ноль был перезаписан для нескольких значений. У нас есть файл с некоторыми общими служебными методами для подобных сценариев. Вот что я добавил, чтобы справиться со сценарием и быть гибким.

function getIfNotSet(value, newValue, overwriteNull, overwriteZero) {
    if (typeof (value) === 'undefined') {
        return newValue;
    } else if (value === null && overwriteNull === true) {
        return newValue;
    } else if (value === 0 && overwriteZero === true) {
        return newValue;
    } else {
        return value;
    }
}

Затем его можно вызвать с последними двумя необязательными параметрами, если я хочу установить только для неопределенных значений или также перезаписать нулевые или нулевые значения. Вот пример обращения к нему, который установит идентификатор на -1, если идентификатор не определен или равен нулю, но не перезаписывает значение 0.

data.ID = Util.getIfNotSet(data.ID, -1, true);
Марк Зеефельдт
источник
1

В наши дни вы действительно можете сделать свой подход с JS:

// Your variable is null
// or '', 0, false, undefined
let x = null;

// Set default value
x = x || 'default value';

console.log(x); // default value

Так что ваш пример будет работать:

const setVariable = localStorage.getItem('value') || 0;
Тарх
источник
0

Работает, даже если значением по умолчанию является логическое значение:

var setVariable = ( (b = 0) => b )( localStorage.getItem('value') );
Tsz Lam Yau
источник
0

Мне кажется, что для текущих реализаций JavaScript,

var [result='default']=[possiblyUndefinedValue]

хороший способ сделать это (используя деконструкцию объекта).

TS
источник
0

Логическое нулевое назначение, решение ES2020 +

Новые операторы в настоящее время добавляются в браузерах, ??=, ||=, и &&=. Этот пост будет посвящен ??=.

Это проверяет, является ли левая сторона неопределенной или нулевой, короткое замыкание, если уже определено. Если нет, то правая сторона назначается левой переменной.

Сравнение методов

// Using ??=
name ??= "Dave"

// Previously, ES2020
name = name ?? "Dave"

// Before that (not equivalent, but commonly used)
name = name || "Dave" // name ||= "Dave"

Основные примеры

let a          // undefined
let b = null
let c = false

a ??= true  // true
b ??= true  // true
c ??= true  // false

// Equivalent to
a = a ?? true

Примеры объектов / массивов

let x = ["foo"]
let y = { foo: "fizz" }

x[0] ??= "bar"  // "foo"
x[1] ??= "bar"  // "bar"

y.foo ??= "buzz"  // "fizz"
y.bar ??= "buzz"  // "buzz"

x  // Array [ "foo", "bar" ]
y  // Object { foo: "fizz", bar: "buzz" }

?? = Поддержка браузера июль 2020 г. - .03%

?? = Документация Mozilla

|| = Документация Mozilla

&& = Документация Mozilla

Gibolt
источник
Является ли действительно хорошей идеей скопировать этот ответ на два других вопроса ( заменить значение, если оно равно null или не определено в JavaScript, и есть ли в JavaScript оператор «нулевого слияния» )? Не лучше ли будет использовать VTC как дубликат или ссылку на связанные вопросы в комментариях?
user4642212
Все вопросы немного отличаются; таковы и ответы. Примеры являются последовательными для улучшения внутреннего контекста с первого взгляда. Вероятно, могли бы связать для более подробной информации, но потребовался бы дополнительный прыжок, который может заставить людей пропустить решение
Gibolt