Несмотря на то, что во многих других ответах яростно это рекомендую, typeof
- плохой выбор . Он никогда не должен использоваться для проверки того, имеют ли переменные значение undefined
, поскольку он действует как комбинированная проверка значения undefined
и наличия переменной. В подавляющем большинстве случаев вы знаете, когда существует переменная, и typeof
просто представит возможность тихого сбоя, если вы сделаете опечатку в имени переменной или в строковом литерале 'undefined'
.
var snapshot = …;
if (typeof snaposhot === 'undefined') {
// ^
// misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;
if (typeof foo === 'undefned') {
// ^
// misspelled – this will never run, but it won’t throw an error!
}
Так что, если вы не делаете обнаружение функций², где есть неопределенность, будет ли данное имя находиться в области (например, проверка typeof module !== 'undefined'
как шаг в коде, специфичном для среды CommonJS), typeof
является вредным выбором при использовании для переменной, и правильный вариант - сравнить значение напрямую:
var foo = …;
if (foo === undefined) {
⋮
}
Некоторые распространенные заблуждения по этому поводу включают:
, что чтение «неинициализированной» переменной (var foo
) или параметра (function bar(foo) { … }
, называемого bar()
) не удастся. Это просто неверно - переменные без явной инициализации и параметры, которым не были заданы значения, всегда становятся undefined
и всегда находятся в области видимости.
, что undefined
может быть перезаписано. Это намного больше. undefined
не является ключевым словом в JavaScript. Вместо этого это свойство глобального объекта с неопределенным значением. Однако, начиная с ES5, это свойство было только для чтения и не конфигурируемым . Ни один современный браузер не позволяет изменять свойство undefined
, и с 2017 года это происходит уже давно. Отсутствие строгого режима также не влияет на поведение undefined
- оно просто заставляет операторы типа undefined = 5
ничего не делать вместо бросков. Так как это не ключевое слово, вы можете объявить переменные с именем undefined
, и эти переменные можно изменить, сделав этот некогда общий шаблон:
(function (undefined) {
// …
})()
больше опаснее, чем использование глобального undefined
. Если вам необходимо совместимость с ES3, замените undefined
на void 0
- не прибегайте к typeof
. (void
всегда был унарным оператором, который оценивается как неопределенное значение для любого операнда.)
С учетом того, как переменные работают нестандартно, пришло время ответить на реальный вопрос: свойства объекта. Нет никаких причин использовать typeof
для свойств объекта. Предыдущее исключение, касающееся обнаружения признаков, здесь не применимо - typeof
имеет специальное поведение только для переменных, а выражения, которые ссылаются на свойства объекта, не являются переменными.
Это:
if (typeof foo.bar === 'undefined') {
⋮
}
равно всегда в точности эквивалентно этому³:
if (foo.bar === undefined) {
⋮
}
и принимая во внимание приведенный выше совет, чтобы не вводить читателей в заблуждение относительно того, почему вы используете typeof
, потому что наиболее разумно использовать ===
для проверки на равенство, потому что это может быть реорганизовано для проверки значение переменной позже, и, поскольку она выглядит просто лучше, вы всегда должны использовать === undefined
³, а также .
Еще одна вещь, которую следует учитывать, когда дело доходит до свойств объекта, - действительно ли вы вообще хотите проверять наличие undefined
. Заданное имя свойства может отсутствовать в объекте (производя значение undefined
при чтении), присутствовать в самом объекте со значением undefined
, присутствовать в прототипе объекта со значением undefined
или присутствовать в любом из с ненулевым значением undefined
. 'key' in obj
скажет вам, находится ли ключ где-нибудь в цепочке прототипов объекта, а Object.prototype.hasOwnProperty.call(obj, 'key')
скажет, находится ли он непосредственно на объекте. В этом ответе я не буду вдаваться в подробности о прототипах и использовании объектов в качестве карт со строковыми ключами, потому что он в основном предназначен для противодействия всем плохим советам в других ответах независимо от возможных интерпретаций исходного вопроса. Читайте о прототипах объектов на MDN , чтобы узнать больше!
¹ необычный выбор примера имени переменной? это настоящий мертвый код из расширения NoScript для Firefox.
² не думай, что не зная, что находится в области видимостиВ общем, все в порядке. Бонусная уязвимость, вызванная злоупотреблением динамической областью действия: Project Zero 1225
³ еще раз при условии, что среда ES5 + и что undefined
относится к свойству undefined
глобального объекта. заменить void 0
в противном случае.