Variable === undefined void typeof variable === "undefined"

jQuery Core Style Guidelines предлагают два разных способа проверить, определена ли переменная.

  • Глобальные переменные: typeof variable === "undefined"
  • Локальные переменные: variable === undefined
  • Свойства: object.prop === undefined

Почему jQuery использует один подход для глобальных переменных, а другой для локалей и свойств?

Ответ 1

Для необъявленных переменных typeof foo вернет строковый литерал "undefined", тогда как проверка идентификатора foo === undefined приведет к ошибке "foo не определен".

Для локальных переменных (которые, как вы знаете, объявлены где-то), такая ошибка не возникает, поэтому проверка идентификации.

Ответ 2

Я буду использовать typeof foo === "undefined" везде. Это никогда не пойдет не так.

Я представляю причину, по которой jQuery рекомендует два разных метода: они определяют свою собственную переменную undefined внутри функции, в которой живет код jQuery, поэтому внутри этой функции undefined безопасно от вмешательства извне. Я бы тоже подумал, что кто-то где-то сравнивает два разных подхода и обнаружил, что foo === undefined быстрее, и поэтому решил, что это путь. [ОБНОВЛЕНИЕ: как отмечено в комментариях, сравнение с undefined также немного короче, что может быть рассмотрено.] Однако выигрыш в практических ситуациях будет совершенно незначителен: эта проверка никогда не будет, когда-либо быть каким-то узким местом, и то, что вы теряете, важно: оценка свойства объекта-объекта для сравнения может вызвать ошибку, тогда как проверка typeof никогда не будет.

Например, в IE для синтаксического анализа XML используется следующее:

var x = new ActiveXObject("Microsoft.XMLDOM");

Чтобы проверить, имеет ли он метод loadXML безопасно:

typeof x.loadXML === "undefined"; // Returns false

С другой стороны:

x.loadXML === undefined; // Throws an error

UPDATE

Еще одно преимущество проверки typeof, о которой я забыл упомянуть, заключается в том, что он также работает с необъявленными переменными, которые не проверяются foo === undefined, и на самом деле выбрасывает ReferenceError. Спасибо @LinusKleen за то, что напомнили мне. Например:

typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError

Нижняя строка: всегда используйте проверку typeof.

Ответ 3

Еще одна причина использования typeof-варианта: undefined может быть переопределена.

undefined = "foo";
var variable = "foo";
if (variable === undefined)
  console.log("eh, what?!");

Результат typeof variable не может.

Обновление: обратите внимание, что в ES5 это не так, глобальное undefined является неконфигурируемым, недоступным для записи свойством:

15.1.1 Value Properties of the Global Object
[...]
15.1.1.3 undefined
The value of undefined is undefined (see 8.1). This property has the attributes
{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

Но он все еще может быть скрыт локальной переменной:

(function() {
  var undefined = "foo";
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})()

или параметр:

(function(undefined) {
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})("foo")

Ответ 4

Поскольку undefined не всегда объявляется, но jQuery объявляет undefined в своей основной функции. Таким образом, они используют безопасное undefined значение внутри, но снаружи, они используют typeof стиль, чтобы быть безопасными.

Ответ 6

Для локальных переменных проверка с помощью localVar === undefined будет работать, потому что они должны быть определены где-то внутри локальной области или они не будут считаться локальными.

Для переменных, которые не являются локальными и не определены нигде, проверка someVar === undefined будет генерировать исключение: Неподготовлено ReferenceError: j не определено

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

function f (x) {
    if (x === undefined) console.log('x is undefined [x === undefined].');
    else console.log('x is not undefined [x === undefined.]');

    if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
    else console.log('x is not undefined [typeof(x) === \'undefined\'].');

    // This will throw exception because what the hell is j? It is nowhere to be found.
    try
    {
        if (j === undefined) console.log('j is undefined [j === undefined].');
        else console.log('j is not undefined [j === undefined].');
    }
    catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}

    // However this will not throw exception
    if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
    else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};

Если мы назовем вышеуказанный код следующим образом:

f();

Выход будет следующим:

x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Если мы назовем вышеуказанный код таким образом (с любым значением фактически):

f(null); 
f(1);

Выход будет:

x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Когда вы выполните проверку следующим образом: typeof x === 'undefined', вы, по сути, просите об этом: Пожалуйста, проверьте, существует ли переменная x (была определена) где-то в исходном коде. (более или менее). Если вы знаете С# или Java, этот тип проверки никогда не выполняется, потому что, если он не существует, он не будет компилироваться.

< == Fiddle Me == >

Ответ 7

Резюме:

Когда в глобальной области видимости мы на самом деле хотим вернуть true, если переменная не объявлена или имеет значение undefined:

var globalVar1;

// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);

// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);

Ответ 8

typeof a === 'undefined' быстрее, чем a === 'undefined' примерно в 2 раза на node v6.9.1.