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
стиль, чтобы быть безопасными.
Ответ 5
Кто заинтересован в увеличении производительности variable === undefined
, может взглянуть здесь, но, похоже, это только оптимизация Chrome.
Ответ 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.