Как проверить «неопределенный» в JavaScript? [Дубликат]

1987

Каков наиболее подходящий способ проверить, есть ли переменная undefined в JavaScript? Я видел несколько возможных способов:

if (window.myVariable)

или

if (typeof(myVariable) != "undefined")

или

if (myVariable) //This throws an error if undefined. Should this be in Try/Catch?
  • 5
    Вы хотите проверить только undefined или null ?
  • 3
    проверьте это stackoverflow.com/questions/27509/…
Показать ещё 7 комментариев
Теги:
undefined

16 ответов

2246
Лучший ответ

Если вам интересно узнать, была ли указана переменная независимо от ее значения, то использование оператора in является самым безопасным способом. Рассмотрим этот пример.

// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"

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

"theFu" in window; // true
"theFoo" in window; // false

Если вам интересно узнать, не была ли указана переменная или имеет значение undefined, используйте оператор typeof.

if (typeof myVar !== 'undefined')

Оператору typeof гарантируется возврат строки. Прямые сравнения с undefined являются неудобными, поскольку undefined могут быть перезаписаны.

window.undefined = "omg";
"omg" == undefined // true

Как отмечала @CMS, это было исправлено в ECMAScript 5th ed., А undefined не записывается.

if (window.myVar) также будет включать эти значения фальши, поэтому он не очень устойчив:

false
0
""
NaN
null
undefined

Благодаря @CMS за то, что ваш третий случай - if (myVariable) также может if (myVariable) ошибку в двух случаях. Во-первых, когда переменная не определена, которая вызывает ReferenceError.

// abc was never declared.
if (abc) {
    // ReferenceError: abc is not defined
} 

Другой случай - когда переменная определена, но имеет функцию геттера, которая вызывает ошибку при вызове. Например,

// or it a property that can throw an error
Object.defineProperty(window, "myVariable", { 
    get: function() { throw new Error("W00t?"); }, 
    set: undefined 
});
if (myVariable) {
    // Error: W00t?
}
  • 7
    @Anurag, третий случай выдаст ReferenceError если myVariable не объявлена ...
  • 0
    @CMS - спасибо, я как-то представил, что myVariable был объявлен где-то, просто без значения.
Показать ещё 24 комментария
984

Я лично использую

myVar === undefined

Внимание: обратите внимание, что === используется над == и что myVar ранее объявлен (не определен).


Мне не нравится typeof myVar === "undefined". Я думаю, что он длинный и ненужный. (Я могу сделать то же самое в меньшем коде.)

Теперь некоторые люди будут кипеть от боли, когда они прочтут это, крича: "Подождите! WAAITTT!!! undefined можно переопределить!"

Круто. Я знаю это. Опять же, большинство переменных в Javascript можно переопределить. Если вы никогда не используете встроенный идентификатор, который можно переопределить?

Если вы будете следовать этому правилу, хорошо для вас: вы не лицемер.

Дело в том, что для того, чтобы делать много реальной работы в JS, разработчикам нужно полагаться на переопределяемые идентификаторы, чтобы быть тем, кем они являются. Я не слышу, как люди говорят мне, что я не должен использовать setTimeout, потому что кто-то может

window.setTimeout = function () {
    alert("Got you now!");
};

Нижняя строка, аргумент "он может быть переопределен", чтобы не использовать raw === undefined, является фиктивным.

(Если вы все еще боитесь переопределения undefined, почему вы слепо интегрируете непроверенный код библиотеки в свою базу кода? Или еще проще: инструмент для переливания.)


Кроме того, как и метод typeof, этот метод может "обнаруживать" необъявленные переменные:

if (window.someVar === undefined) {
    doSomething();
}

Но обе эти технологии просачиваются в их абстракции. Я призываю вас не использовать это или даже

if (typeof myVar !== "undefined") {
    doSomething();
}

Рассмотрим:

var iAmUndefined;

Чтобы узнать, объявлена ​​ли эта переменная или нет, вам может потребоваться обратиться к оператору in. (Во многих случаях вы можете просто прочитать код O_o).

if ("myVar" in window) {
    doSomething();
}

Но подождите! Там еще! Что, если какая-то прототипная магическая цепочка происходит...? Теперь даже верхнего оператора in недостаточно. (Хорошо, я закончил здесь эту часть, кроме как сказать, что в 99% случаев === undefined (и **** cough **** typeof) работает отлично. Если вам действительно все равно, вы может прочитать об этом предмете самостоятельно.)

  • 47
    Чуть более вероятно, что undefined может быть переопределен только потому, что люди используют его для таких проверок. Некоторые люди обычно ставят константу слева при выполнении таких проверок: if (undefined == someVariable) . Для этого требуется только опечатка, чтобы молча переопределить undefined : if (undefined = someVariable) .
  • 45
    Я никогда не пишу код, который не undefined на LHS. Даже если бы я это сделал, тот факт, что я использую === вместо == делает опечатку крайне маловероятной. Но тот факт, что == неверно, больше беспокоит. В любом случае, подобную ошибку обычно легко найти. typeof x == "undefned" как эта ошибка: typeof x == "undefned" .
Показать ещё 20 комментариев
158

Использование typeof - мое предпочтение. Он будет работать, когда переменная никогда не была объявлена, в отличие от любого сравнения с операторами == или === или типом принуждения с использованием if. (undefined, в отличие от null, также может быть переопределено в средах ECMAScript 3, что делает его ненадежным для сравнения, хотя почти все обычные среды теперь совместимы с ECMAScript 5 или выше).

if (typeof someUndeclaredVariable == "undefined") {
    // Works
}

if (someUndeclaredVariable === undefined) { 
    // Throws an error
}
  • 18
    Возможно, вы захотите проверить, определена ли уже определенная глобальная переменная, представляющая часть функциональности. Например, код библиотеки может захотеть проверить, что библиотека еще не была включена ранее.
  • 1
    «XYZ» в окне или «XYZ» в себе гораздо лучше
Показать ещё 7 комментариев
54

Вам нужно использовать typeof.

if (typeof something != "undefined") {
    // ...
}
  • 6
    Или просто something !== undefined , если вы уже сделали var undefined , предварительно осторожно.
  • 3
    Приятно видеть, что вы добавили цитаты сейчас. Однако, как упоминалось в моем ответе , обратите внимание, что строгое сравнение ( !== ) в этом случае не требуется, так как typeof всегда будет возвращать строку.
Показать ещё 2 комментария
21

Если это undefined, он не будет равен строке, содержащей символы "undefined", поскольку строка не undefined.

Вы можете проверить тип переменной:

if (typeof(something) != "undefined") ...

Иногда вам даже не нужно проверять тип. Если значение переменной не может быть оценено в false, когда оно установлено (например, если это функция), вы можете просто оценить переменную. Пример:

if (something) {
  something(param);
}
  • 11
    Нет необходимости в скобках: typeof является оператором, а не функцией.
  • 5
    @Tim - это можно использовать в обоих направлениях.
Показать ещё 2 комментария
17

Некоторые сценарии, иллюстрирующие результаты различных ответов: http://jsfiddle.net/drzaus/UVjM4/

(Обратите внимание, что использование тегов var для in имеет значение, когда в обертованной области)

Код для справки:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

И результаты:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined
  • 1
    обратите внимание на использование undefined в undefined области видимости; это не только защищает от (необычного) случая «о, но undefined может быть переопределено», но также «помогает» в минификации.
16
if (typeof foo == 'undefined') {
 // Do something
};

Обратите внимание, что в этом случае не требуется строгое сравнение (!==), так как typeof всегда будет возвращать строку.

  • 3
    Что с точкой с запятой ( }; )?
  • 2
    @JP: точка с запятой после закрывающей скобки - просто пустое утверждение.
Показать ещё 4 комментария
15

В в этой статье Я читал, что фреймворки, такие как Underscore.js используйте эту функцию:

function isUndefined(obj){
    return obj === void 0;
}
15

Обновление 2018-07-25

Прошло почти пять лет с момента создания этого сообщения, и JavaScript прошел долгий путь. Повторяя тесты в исходном посте, я не нашел постоянной разницы между следующими методами тестирования:

  • abc === undefined
  • abc === void 0
  • typeof abc == 'undefined'
  • typeof abc === 'undefined'

Даже когда я модифицировал тесты, чтобы предотвратить их оптимизацию, различия были незначительными. Поэтому я бы рекомендовал abc === undefined для ясности.

Соответствующий контент из chrome://version:

  • Google Chrome: 67.0.3396.99 (официальная сборка) (64-разрядная версия) (когорт: стабильный)
  • Версия: a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b-refs/branch-heads/3396 @{# 790}
  • ОС: Windows
  • JavaScript: V8 6.7.288.46
  • Пользовательский агент: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, например, Gecko) Chrome/67.0.3396.99 Safari/537.36

Оригинальный пост 2013-11-01

В Google Chrome, следующий был чуть - чуть быстрее, чем typeof тест:

if (abc === void 0) {
    // Undefined
}

Разница была незначительной. Однако этот код является более кратким и более ясным с точки зрения того, кто знает, что означает void 0. Обратите внимание, однако, что abc все равно должен быть объявлен.

Оба typeof и void были значительно быстрее, чем сравнение непосредственно с undefined. Я использовал следующий тестовый формат в консоли разработчика Chrome:

var abc;
start = +new Date();
for (var i = 0; i < 10000000; i++) {
    if (TEST) {
        void 1;
    }
}
end = +new Date();
end - start;

Результаты были следующими:

Test: | abc === undefined      abc === void 0      typeof abc == 'undefined'
------+---------------------------------------------------------------------
x10M  |     13678 ms               9854 ms                 9888 ms
  x1  |    1367.8 ns              985.4 ns                988.8 ns

Обратите внимание, что первая строка находится в миллисекундах, а вторая - в наносекундах. Разница в 3,4 наносекунды - ничто. Время было довольно последовательным в последующих тестах.

  • 0
    Ой, так душераздирающе, что это -1; Я потратил много времени на тестирование этого. Ну что ж. Это хорошая информация, поэтому я оставлю это здесь. Помните, не используйте === для проверки undefined !
  • 1
    я предполагаю, что -1 был из-за 1) <q> и более понятен тому, кто знает, что означает void 0 </ q>, так как void 0 звучит более необычно для меня, 2) вместо этого вы должны поделиться своими тестами перфоратора , но в основном 3) ваш первый пример ( abc === void 0 ) выдает исключение, если abc не определено.
Показать ещё 3 комментария
10

Самый надежный способ проверки undefined - использовать void 0.

Это совместимо с более старыми и более старыми браузерами и не может быть перезаписано, например, как window.undefined.

if( myVar === void 0){
    //yup it undefined
}
  • 1
    Это недооценено и ИМХО предпочтительный способ проверить что-то неопределенное.
  • 1
    Абсолютно правильно, но я думаю, что если undefined !== void 0 , у вас, вероятно, есть другие серьезные проблемы в указанной кодовой базе.
9

Лично я всегда использую следующее:

var x;
if( x === undefined) {
    //Do something here
}
else {
   //Do something else here
}

Свойство window.undefined не доступно для записи во всех современных браузерах (JavaScript 1.8.5 или новее). Из документации Mozilla: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined, я вижу следующее: Одна из причин использования typeof() заключается в том, что она не выдает ошибку, если переменная имеет не определено.

Я предпочитаю использовать подход

x === undefined 

потому что он терпит неудачу и взрывается в моем лице, а не бесшумно проходит/терпит неудачу, если x не был объявлен ранее. Это предупреждает меня, что x не объявлен. Я считаю, что все переменные, используемые в JavaScript, должны быть объявлены.

  • 0
    вы можете переопределить undefined используя контекстные оболочки: (function($, undefined){ /* undefined is 'abc' in here */ })(jQuery, 'abc'); Вот почему пользователи жалуются на то, что это технически небезопасно, если вы не уверены на 100%, что знаете, где выполняется ваш код.
  • 0
    Замечательный момент, когда нужно объявить необъявленную переменную - этого не происходит с typeof.
4

Поскольку ни один из ответов не помог мне, я предлагаю сделать это. Это работало для меня в Internet Explorer 8:

if (typeof variable_name.value === 'undefined') {
    // variable_name is undefined
}
3
// x has not been defined before
if (typeof x === 'undefined') { // Evaluates to true without errors.
   // These statements execute.
}

if (x === undefined) { // Throws a ReferenceError

}
3

Напротив ответа @Thomas Eding:

Если я забыл объявить myVar в своем коде, тогда я получу myVar is not defined.

Возьмем реальный пример:

У меня есть имя переменной, но я не уверен, что она объявлена ​​где-то или нет.

Затем ответ @Anurag поможет:

var myVariableToCheck = 'myVar';
if (window[myVariableToCheck] === undefined)
    console.log("Not declared or declared, but undefined.");

// Or you can check it directly 
if (window['myVar'] === undefined) 
    console.log("Not declared or declared, but undefined.");
  • 2
    Получение такого myVar is not defined ошибка будет хорошей вещью, особенно если вы специально напишите «Если я забуду объявить» [выделено мной]. Мне нравится, когда я получаю ошибки до запуска моего кода. Если вы хотите узнать больше моего мнения о вашем ответе, я сделал соответствующие комментарии под моим ответом.
1
    var x;
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    if (typeof y === "undefined") {
        alert ("I am not even declared.")
    };

    /* One more thing to understand: typeof ==='undefined' also checks 
       for if a variable is declared, but no value is assigned. In other 
       words, the variable is declared, but not defined. */

    // Will repeat above logic of x for typeof === 'undefined'
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    /* So typeof === 'undefined' works for both, but x === undefined 
       only works for a variable which is at least declared. */

    /* Say if I try using typeof === undefined (not in quotes) for 
       a variable which is not even declared, we will get run a 
       time error. */

    if (z === undefined) {
        alert ("I am neither declared nor defined.")
    };
    // I got this error for z ReferenceError: z is not defined 
0

Я использую его как параметр функции и исключаю его при выполнении функции таким образом, что получаю "реальный" undefined. Хотя это требует, чтобы вы включили код внутри функции. Я нашел это при чтении источника jQuery.

undefined = 2;

(function (undefined) {
   console.log(undefined); // prints out undefined
   // and for comparison:
   if (undeclaredvar === undefined) console.log("it works!")
})()

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

  • 3
    Это даст ReferenceError, если var undeclaredvar действительно необъявлена. Если это атрибут, то это работает, например: var undeclaredvar = window.someUndeclaredVar; if (undeclaredvar === undefined) console.log("it works!"). Пожалуйста, проверьте ваш пример перед публикацией.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню