Как проверить неопределенную или нулевую переменную в JavaScript?

500

Мы часто используем следующий шаблон кода в нашем коде JavaScript

if (typeof(some_variable) != 'undefined' && some_variable != null)
{
    // Do something with some_variable
}

Есть ли менее подробный способ проверки, который имеет такой же эффект?

По мнению некоторых форумов и литературы, просто следующее должно иметь такой же эффект.

if (some_variable)
{
    // Do something with some_variable
}

К сожалению, Firebug оценивает такой оператор как ошибку во время выполнения, когда some_variableон не определен, тогда как первый подходит для него. Это только (нежелательное) поведение Firebug или действительно есть какая-то разница между этими двумя способами?

Томас Вана
источник
46
if(some_variable) { ... }не выполнится, если some_variableесть falseили 0или ...
kennytm
хороший момент;) Но допустим, я знаю, что это не может быть false или 0, и я просто хочу проверить, могу ли я использовать его в некоторой логике (в виде строки, массива и т. д.)
Томас Вана
Связанный: stackoverflow.com/questions/27509/…
Йорн Шоу-Роде
2
... или пустая строка.
Дэвид Дан

Ответы:

333

Вы должны различать случаи:

  1. Переменные могут быть undefinedили необъявленными . Вы получите ошибку, если получите доступ к необъявленной переменной в любом контексте, кроме typeof.
if(typeof someUndeclaredVar == whatever) // works
if(someUndeclaredVar) // throws error

Переменная, которая была объявлена, но не инициализирована, является undefined.

let foo;
if (foo) //evaluates to false because foo === undefined
  1. Неопределенные свойства , как someExistingObj.someUndefProperty. Неопределенное свойство не приводит к ошибке и просто возвращает значение undefined, которое при преобразовании в логическое значение оценивается как false. Так что, если вас не волнует 0и false, использование if(obj.undefProp)в порядке. Есть общая идиома, основанная на этом факте:

    value = obj.prop || defaultValue

    что означает «если objесть свойство prop, присвойте его value, в противном случае присвойте значение по умолчанию defautValue».

    Некоторые люди считают, что это поведение сбивает с толку, утверждая, что это приводит к трудно обнаруживаемым ошибкам, и рекомендуют inвместо этого использовать оператор

    value = ('prop' in obj) ? obj.prop : defaultValue
user187291
источник
1
Тогда вы могли бы поговорить о hasOwnProperty и прототипах. 'indexOf' в []! == [] .hasOwnProperty ('indexOf')
Alsciende
1
Да, я подумал добавить это, но решил пожертвовать полнотой ради краткости. ;)
user187291
52
вы не решаете проблему 0 и ложь
TMS
12
Вы имеете в виду необъявленные переменные. Переменная может быть объявлена, но все равно иметь значение undefined.
Tgr
1
А также обратите внимание, что typeofвозвращает строку. Так что не var myVar; typeof(myVar)==undefinedвозвращается . falsetrue
Ризм
417

Я думаю, что самый эффективный способ проверить на «значение есть nullили undefined» это

if ( some_variable == null ){
  // some_variable is either null or undefined
}

Итак, эти две строки эквивалентны:

if ( typeof(some_variable) !== "undefined" && some_variable !== null ) {}
if ( some_variable != null ) {}

Примечание 1

Как упоминалось в вопросе, короткий вариант требует, чтобы some_variableон был объявлен, в противном случае будет сгенерировано ReferenceError. Однако во многих случаях вы можете предположить, что это безопасно:

проверьте наличие необязательных аргументов:

function(foo){
    if( foo == null ) {...}

проверить свойства на существующем объекте

if(my_obj.foo == null) {...}

С другой стороны, typeofможет иметь дело с необъявленными глобальными переменными (просто возвращает undefined). Тем не менее, как объяснил Альсьенде, эти случаи должны быть сведены к минимуму по веским причинам.

Заметка 2

Этот - даже более короткий - вариант не эквивалентен:

if ( !some_variable ) {
  // some_variable is either null, undefined, 0, NaN, false, or an empty string
}

так

if ( some_variable ) {
  // we don't get here if some_variable is null, undefined, 0, NaN, false, or ""
}

Заметка 3

В общем, рекомендуется использовать ===вместо ==. Предлагаемое решение является исключением из этого правила. Проверки синтаксиса JSHint даже предоставляет eqnullопцию по этой причине.

Из руководства по стилю jQuery :

Строгие проверки на равенство (===) должны использоваться в пользу ==. Единственное исключение - при проверке неопределенности и нуля посредством нуля.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;
Mar10
источник
1
Очень важное отличие (о котором уже упоминалось в вопросе между прочим). Вот почему все используют typeof. Извините, но я не понимаю, где ваш ответ полезен, вы просто заявляете, что было сказано в вопросе, и в первых нескольких строках вы заявляете, что это даже неправильно.
TMS
33
Извините, но я должен не согласиться ;-) Использование == nullimho наиболее эффективно для проверки на 'null или undefined' (это тема вопросов). Это ни в коем случае не редкость (используется 43 раза в jQuery 1.9.1), так как очень часто вы знаете, что переменная была объявлена ​​- или вы проверяете свойство существующего объекта, например if( o.foo == null).
марта
1
@ mar10 (aUndefinedVar == null) выдает сообщение об ошибке «aUndefinedVar не определен».
Rannnn
7
Спасибо за этот краткий вариант. В 99% моего кода нет необходимости различать нулевой и неопределенный, поэтому краткость этой проверки приводит к менее загроможденному коду.
Ян Лавджой
1
Чтобы предотвратить ошибку ReferenceError при проверке глобальной переменной, используйте window.someProperty == null. Для локальных переменных вы можете легко убедиться, что они объявлены: вместо записи if (...) {var local = ""}пишитеvar local; if (...) { local = ""; }
Aloso
66

Проверка нуля с нормальным равенством также вернет true для неопределенного.

if (window.variable == null) alert('variable is null or undefined');

JS Equality

Semra
источник
4
NaN не равно Нан?
Шарджил Ахмед
2
@monotheist NaN не равен NaN (см . страницу NaN MDN ). Javascript использует IEEE-754 в качестве плавающей запятой, которая определяет это поведение. Есть некоторые мысли по этому поводу
Стивен
1
@SharjeelAhmed Математически исправлено. NaNиз разностного уравнения никогда нельзя ожидать равного
Thaina
28

В более новых стандартах JavaScript, таких как ES5 и ES6, вы можете просто сказать,

> Boolean(0) //false
> Boolean(null)  //false
> Boolean(undefined) //false

все возвращают false, что похоже на проверку пустых переменных в Python. Так что если вы хотите написать условную логику вокруг переменной, просто скажите

if (Boolean(myvar)){
   // Do something
}

здесь «null» или «пустая строка» или «undefined» будут обрабатываться эффективно.

Нарен Йеллавула
источник
2
поддерживается до как ie5, почему это не более известно !?
Химматоры
12
OP просто хотел проверить разные значения, nullа undefinedдругие ложные значения должны возвращать true!
Андре Фигейредо
1
Это не добавляет никакой ценности в условном выражении. Условие вычисляется точно так же и по- прежнему возвращает ложь для 0, NaN. Это для случаев, когда вы хотите зафиксировать истинность объекта, не сохраняя ссылку на объект, чтобы вы могли сохранить его, а не какой-либо потенциально большой объект. К вашему сведению, это также эквивалентно тому !!value, что первый !отрицает правдивость, а второй снова отрицает его.
erich2k8
> К вашему сведению это также эквивалентно !! стоимости, которая первая! отрицает правдивость Какой FYI также эквивалентен тому, if (var)который будет приведен к логическому
значению
2
Хотя в буквальном смысле используется ключевое слово undefined , Boolean(undefined)работает, пробовать это с неопределенной переменной не работает, и в этом весь смысл проверки на нулевой или неопределенный. Это: if (Boolean(undeclareVarName)) { console.log('yes'); } else { console.log('no'); }генерирует ReferenceError, говорящее «ReferenceError: undeclareVarName не определено»
Стивен П.
22

Если вы попытаетесь сослаться на необъявленную переменную, во всех реализациях JavaScript будет выдана ошибка.

Свойства объектов не подчиняются тем же условиям. Если свойство объекта не было определено, ошибка не будет выдана, если вы попытаетесь получить к нему доступ. Таким образом, в этой ситуации вы можете сократить:

 if (typeof(myObj.some_property) != "undefined" && myObj.some_property != null)

в

if (myObj.some_property != null)

Имея это в виду и тот факт, что глобальные переменные доступны как свойства глобального объекта ( windowв случае браузера), вы можете использовать следующее для глобальных переменных:

if (window.some_variable != null) {
    // Do something with some_variable
}

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

Энди Э
источник
11
Вы пропустите NaN, 0, "" и ложь, потому что они не являются ни нулевыми, ни неопределенными, но также ложными.
Андреас Кёберле
@ Андреас Коберле прав. Даже оператор нестрогого равенства говорит, что null отличается от NaN, 0, "" и false. Вы должны сделать, if (myObj.some_property != null)чтобы получить эквивалентное поведение.
thejoshwolfe
15

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

Функция, test(val)которая проверяет nullили undefinedдолжна иметь следующие характеристики:

 test(null)         => true
 test(undefined)    => true
 test(0)            => false
 test(1)            => false
 test(true)         => false
 test(false)        => false
 test('s')          => false
 test([])           => false

Давайте посмотрим, какие из идей здесь действительно проходят наше испытание.

Эти работы:

val == null
val === null || val === undefined
typeof(val) == 'undefined' || val == null
typeof(val) === 'undefined' || val === null

Они не работают:

typeof(val) === 'undefined'
!!val

Я создал запись jsperf, чтобы сравнить правильность и производительность этих подходов. Результаты пока неубедительны, так как не было достаточно прогонов на разных браузерах / платформах. Пожалуйста, найдите минутку, чтобы запустить тест на вашем компьютере!

В настоящее время кажется, что простой val == nullтест дает лучшую производительность. Это также в значительной степени самый короткий. Тест может быть отменен, val != nullесли вы хотите дополнения.

Дрю Ноакс
источник
12

это единственный случай, в котором ==следует использовать:

if (val == null) console.log('val is null or undefined')
Yukulélé
источник
3
этот ответ около 2019 года имеет недостаток голосов, но это KISS для этого варианта использования. И val != nullнаоборот, только один, = и поскольку на @Yukulele это ЕДИНСТВЕННЫЙ, ==вы будете знать, что он делает, когда вы его видите.
ДКеблер
7

Поскольку не существует единого полного и правильного ответа, я постараюсь обобщить:

В общем, выражение:

if (typeof(variable) != "undefined" && variable != null)

не может быть упрощено, потому что это variableможет быть необъявленным, поэтому, если пропустить typeof(variable) != "undefined", в ReferenceError. Но вы можете упростить выражение в соответствии с контекстом :

Если variableэто глобально , вы можете упростить до:

if (window.variable != null)

Если он локальный , вы можете избежать ситуаций, когда эта переменная не объявлена, а также упростить до:

if (variable != null)

Если это свойство объекта , вам не нужно беспокоиться о ReferenceError:

if (obj.property != null)
TMS
источник
Является navigatorчастью window? Когда мы получим исключение для navigator is not defined, можем ли мы использовать window.navigator != nullтест?
августа
5

Вы можете просто проверить, имеет ли переменная значение или нет. Смысл,

if( myVariable ) {
//mayVariable is not :
//null
//undefined
//NaN
//empty string ("")
//0
//false

}

Если вы не знаете, существует ли переменная (то есть, если она была объявлена), вам следует проверить с помощью оператора typeof. например

if( typeof myVariable !== 'undefined' ) {
    // myVariable will get resolved and it is defined
}
DDave
источник
4

Я сделал это с помощью этого метода

сохранить идентификатор в некоторой переменной

var someVariable = document.getElementById("someId");

тогда используйте условие if

if(someVariable === ""){
 //logic
} else if(someVariable !== ""){
 //logic
}
Маб киани
источник
4

Это пример очень редкого случая, когда его рекомендуется использовать ==вместо ===. Выражение somevar == nullвернет true для undefinedи null, но false для всего остального (ошибка, если переменная не объявлена).

Использование !=перевернет результат, как и ожидалось.

Современные редакторы не будут предупреждать об использовании ==или работе !=с ними null, так как это почти всегда желаемое поведение.

Наиболее распространенные сравнения:

undeffinedVar == null     // true
obj.undefinedProp == null // true
null == null              // true
0 == null                 // false
'0' == null               // false
'' == null                // false

Попробуй сам:

let undefinedVar;
console.table([
    { test : undefinedVar,     result: undefinedVar     == null },
    { test : {}.undefinedProp, result: {}.undefinedProp == null },
    { test : null,             result: null             == null },
    { test : false,            result: false            == null },
    { test : 0,                result: 0                == null },
    { test : '',               result: ''               == null },
    { test : '0',              result: '0'              == null },
]);
Сабо
источник
3

Как упоминалось в одном из ответов, вам может повезти, если вы говорите о переменной, имеющей глобальную область видимости. Как вы, возможно, знаете, переменные, которые вы определяете глобально, как правило, добавляются к объекту windows. Вы можете воспользоваться этим фактом, поэтому допустим, что вы обращаетесь к переменной с именем bleh, просто используйте оператор с двойным инвертированием (!!)

!!window['bleh'];

Это вернет false, пока bleh не был объявлен и ему не присвоено значение.

Фарас
источник
3

Вот еще один способ использования метода Array include () :

[undefined, null].includes(value)
Джейсон
источник
Это не работает! ReferenceError: значение не определено
Sébastien Temprado
1
Это должно быть значение, которое вы хотите проверить.
a2441918
2

независимо от того, что yyy не определено или равно нулю, оно вернет true

if (typeof yyy == 'undefined' || !yyy) {
    console.log('yes');
} else {
    console.log('no');
}

да

if (!(typeof yyy == 'undefined' || !yyy)) {
    console.log('yes');
} else {
    console.log('no');
}

нет

Терри Лин
источник
2

Откройте инструменты разработчика в вашем браузере и просто попробуйте код, показанный на рисунке ниже.

Img1 Img2

Акаш Прит
источник
2

Чтобы понять, давайте проанализируем, какое будет значение, возвращаемое Javascript Engine при преобразовании undefined, null и '' (также пустая строка). Вы можете непосредственно проверить то же самое на своей консоли разработчика.

введите описание изображения здесь

Вы можете видеть, что все преобразуются в ложные, то есть все эти три предполагают «отсутствие существования» в javascript. Так что вам не нужно явно проверять все три в вашем коде, как показано ниже.

if (a === undefined || a === null || a==='') {
    console.log("Nothing");
} else {
    console.log("Something");
}

Также я хочу отметить еще одну вещь.

Что будет результатом логического (0)?

Конечно ложно. Это создаст ошибку в вашем коде, когда 0 является допустимым значением ожидаемого результата. Поэтому, пожалуйста, убедитесь, что вы проверили это при написании кода.

Код-EZ
источник
2

Подобно тому, что у вас есть, вы могли бы сделать что-то вроде

if (some_variable === undefined || some_variable === null) { do stuff }

gpap
источник
0

Тестирование nullity ( if (value == null)) или non-nullity ( if (value != null)) менее многословно, чем тестирование статуса определения переменной.

Более того, тестирование if (value)(или if( obj.property)) для обеспечения существования вашей переменной (или свойства объекта) завершается неудачей, если оно определено с помощью логического falseзначения. Пусть покупатель будет бдителен :)

lucsorel
источник
0

Оба значения можно легко различить с помощью оператора строгого сравнения:

Рабочий пример на:

http://www.thesstech.com/tryme?filename=nullandundefined

Образец кода:

function compare(){
    var a = null; //variable assigned null value
    var b;  // undefined
    if (a === b){
        document.write("a and b have same datatype.");
    }
    else{
        document.write("a and b have different datatype.");
    }   
}
Сохаил Ариф
источник
0

Если целью оператора if является проверка nullили undefinedзначения перед присвоением значения переменной, вы можете использовать оператор Nullish Coalescing Operator , который наконец-то доступен в JavaScript, хотя поддержка браузера ограничена. По данным caniuse , поддерживается только 48,34% браузеров (по состоянию на апрель 2020 года).

const a = some_variable ?? '';

Это гарантирует, что переменная будет присвоена пустой строке (или любому другому значению по умолчанию), если some_variableесть nullили undefined.

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

wentjun
источник
-1

Вы должны определить функцию этой формы:

validate = function(some_variable){
    return(typeof(some_variable) != 'undefined' && some_variable != null)
}
ljofre
источник
Это сгенерирует тот же ReferenceError, если переменная не объявлена.
Чад
-1

В ES5 или ES6, если вам нужно проверить это несколько раз, вы делаете следующее:

const excluded = [null, undefined, ''];

if (!exluded.includes(varToCheck) {
  // it will bee not null, not undefined and not void string
}

vladernn
источник
-1

С Ramda вы можете просто сделать так, чтобы R.isNil(yourValue) Lodash и другие вспомогательные библиотеки выполняли ту же функцию.

Марк Джексон
источник