undefined != undefined
undefined
(неопределённое значение) — элементарное значение типа Undefined
, используемое, когда переменной или свойства объекта не существует или ему ещё не было присвоено значение. Т.е. положительность условия
foo.bar == undefined
или
typeof foo.bar == 'undefined'
может означать как отсутствие свойства bar
у объекта foo
, так и его наличие, но со значением undefined
. Равно как и положительность условия
typeof undef == 'undefined'
может означать отсутствие переменной undef
или её наличие со значением undefined
. Обратите внимание, что
запись undef == undefined
вызовет исключение ReferenceError
в случае, если переменной undef
не существует. В то время как typeof undef
выполнится корректно.
В случаях, когда необходимо проверить наличие свойства с любым значением, в том числе undefined
, необходимо проверять именно наличие свойства, а не его значение. Для этого предназначен оператор in
.
if (foo.bar == undefined) {
alert('Свойства bar у объекта foo или нет, или оно равно undefined');
}
if ('bar' in foo) {
alert('Свойство bar у объекта foo есть.');
}
Проверить наличие глобальной переменной можно проверяя наличие свойства у window
.
if ('t' in window) {
alert('Существует глобальная переменная t');
}
Наличие локальной переменной проверить нет возможности, но это, как правило, и не требуется, т.к. локальное пространство имён находится под большим контролем, нежели глобальное.
Если в функцию не передать аргумент, то к ней придёт undefined
. Также как если передать undefined
придёт, разумеется, он же. Поэтому, если нужно узнать именно, был ли передан аргумент, вне зависимости от его значения, то нужно проверять свойство length
объекта arguments
. Оно будет равно количеству переданных в функцию аргументов.
Реализуем, например, метод push
для массивов, который полученные аргументы добавляет в массив. Он конечно же должен уметь добавлять undefined
.
Array.prototype.push = function() {
for (var i = 0; i < arguments.length; i++) {
this[this.length] = arguments[i];
}
};
В последнее время также распространена эмуляция свойств методом, который при отсутствии аргумента притворяется геттером, а при наличии — сеттером. Здесь тоже важно проверять передан ли аргумент, а не что именно передано.
// Неправильно, при таком подходе невозможно присвоить undefined
foo.property = function(value) {
if (typeof value == 'undefined') {
// Возвращаем значение
} else {
// Присваиваем значение
}
}
// Правильно
foo.property = function(value) {
if (arguments.length > 0) {
// Присваиваем значение
} else {
// Возвращаем значение
}
}
undefined
undefined
это всего лишь заранее определённая глобальная переменная. Её, как и любую другую переменную, можно переопределить, и тогда более компактная конструкция foo.bar == undefined
работать не будет. Поэтому для большей отказоустойчивости скриптов необходимо использовать или typeof, или "добывать" для себя значение типа Undefined
. Для этого можно воспользоваться несколькими способами.
Во-первых, существует конструкция void
, которая всегда возвращает undefined
.
var my_undef = void 0;
Во-вторых, можно описать локальную переменную, но не инициализировать её.
(function() {
var undefined;
})();
В-третьих, можно завернуть исполняемый скрипт в безымянную функцию, описать у неё параметр, но сам параметр при вызове не передавать.
(function(undefined) {
})();