Обнаружение неопределенного свойства объекта

Ответы:

2681

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

if(o.myProperty === undefined) {
  alert("myProperty value is the special value `undefined`");
}

Чтобы проверить, действительно ли объект не имеет такого свойства и, следовательно, вернется undefinedпо умолчанию при попытке доступа к нему:

if(!o.hasOwnProperty('myProperty')) {
  alert("myProperty does not exist");
}

Чтобы проверить, является ли значение, связанное с идентификатором, специальным значением undefined, или этот идентификатор не был объявлен. Примечание: этот метод является единственным способом ссылки на необъявленный (примечание: отличается от значения undefined) идентификатор без ранней ошибки:

if(typeof myVariable === 'undefined') {
  alert('myVariable is either the special value `undefined`, or it has not been declared');
}

В версиях JavaScript до ECMAScript 5 свойство с именем «undefined» в глобальном объекте было доступно для записи, и поэтому простая проверка foo === undefinedмогла бы привести к неожиданным результатам, если бы она была случайно переопределена. В современном JavaScript свойство доступно только для чтения.

Однако в современном JavaScript «undefined» не является ключевым словом, и поэтому переменные внутри функций могут быть названы «undefined» и скрывать глобальное свойство.

Если вас беспокоит этот (маловероятный) крайний случай, вы можете использовать оператор void для получения самого специального undefinedзначения:

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}
Ry-
источник
9
если что-то имеет значение null, то оно определено (как null), но вы также можете сопрягать проверки тоже. Досадная деталь приведенного выше кода заключается в том, что вы не можете определить функцию для проверки, ну, вы можете определить функцию ... но попробуйте ее использовать.
Neu-rah
5
@ neu-rah, почему ты не можешь написать функцию? почему бы не что-то вроде этой работы? Кажется, это работает для меня. Есть ли дело, которое я не рассматриваю? jsfiddle.net/djH9N/6
Зак
7
@Zack Ваши тесты для isNullorUndefined не учитывали случай, когда вы вызываете isNullOrUndefined (f), а f необъявлено (т. Е. Там, где нет объявления "var f").
pnkfelix
109
Бла, тысячи голосов сейчас. Это худший из возможных способов сделать это. Я надеюсь, что прохожие увидят этот комментарий и решат проверить… хм… другие ответы.
Ry-
17
Вы можете просто использовать obj !== undefinedсейчас. undefinedимел обыкновение быть изменчивым, как undefined = 1234то, что вызвало бы интересные результаты. Но после Ecmascript 5 он больше не доступен для записи, поэтому мы можем использовать более простую версию. codereadability.com/how-to-check-for-undefined-in-javascript
Бруно Букколо
899

Я считаю, что есть ряд неправильных ответов на эту тему. Вопреки распространенному мнению, «undefined» не является ключевым словом в JavaScript и может фактически иметь присвоенное ему значение.

Правильный код

Самый надежный способ выполнить этот тест:

if (typeof myVar === "undefined")

Это всегда будет возвращать правильный результат, и даже обрабатывает ситуацию, когда myVarне объявлено.

Вырожденный код. НЕ ИСПОЛЬЗУЙТЕ.

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) {
    alert("You have been misled. Run away!");
}

Кроме того, myVar === undefinedвозникнет ошибка в ситуации, когда myVar не объявлен.

MarkPflug
источник
133
+1 за то, что заметил, что myVar === undefined вызовет ошибку, если myVar не был объявлен
Энрике
73
Я нахожу первое оправдание, данное здесь, чтобы не использовать === undefinedизумление. Да, вы можете назначить undefined, но для этого нет законных оснований, и вполне предсказуемо, что это может нарушить ваш код. В C вы можете #define true false, а в Python вы можете назначить Trueи False, но люди не чувствуют необходимости разрабатывать свой код на этих языках таким образом, чтобы защитить себя от возможности умышленного саботажа своей собственной среды в другом месте кода. , Почему возможность присвоения undefinedдаже стоит рассмотреть здесь?
Марк Амери
19
в дополнение к комментариям Маркса я не получаю следующее: «myVar === undefined вызовет ошибку в ситуации, когда myVar не объявлен». - почему это плохо? Почему я не хочу иметь ошибку, если я ссылаюсь на необъявленные переменные?
эйс
5
Также имейте в виду, что вы всегда можете сделать, void 0чтобы получить значение, на которое undefinedуказывает. Так что вы можете сделать if (myVar === void 0). 0не является специальным, вы можете буквально поместить любое выражение там.
Клавдиу
28
В современных браузерах (FF4 +, IE9 +, Chrome неизвестно) изменение уже невозможно undefined. MDN: не определено
user247702
228

Несмотря на то, что здесь яростно рекомендуют многие другие ответы, 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. Если вам нужно быть совместимым undefinedс ES3, замените на void 0- не прибегайте к typeof. ( voidвсегда был унарным оператором, который оценивается как неопределенное значение для любого операнда.)

С тем, как переменные работают вне пути, пришло время обратиться к фактическому вопросу: свойствам объекта. Нет никаких причин когда-либо использовать typeofдля свойств объекта. Более раннее исключение, касающееся обнаружения признаков, здесь не применимо - typeofимеет специальное поведение только для переменных, а выражения, которые ссылаются на свойства объекта, не являются переменными.

Эта:

if (typeof foo.bar === 'undefined') {
    
}

это всегда точно эквивалент в this³:

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иначе.

Ry-
источник
@BenjaminGruenbaum Правда, но полностью вводит в заблуждение. Любой нестандартный контекст может определять свой собственный undefined, скрывая контекст по умолчанию. Что для большинства практических целей имеет тот же эффект, что и перезапись.
Blgt
23
@blgt Это параноидально и не имеет никакого отношения к чему-либо практическому. Каждый контекст может переопределять console.log, переопределять методы-прототипы Array и даже переопределять перехват Function.prototype.call` и изменять каждый раз, когда вы вызываете функцию в JavaScript. Защита от этого очень параноидальна и довольно глупа. Как я (и Minitech) сказал, вы можете использовать void 0для сравнения с неопределенным, но опять же - это глупо и излишне.
Бенджамин Грюнбаум
19
Я бы хотел, чтобы у меня было больше одного голоса. Это самый правильный ответ. Я действительно хочу перестать видеть typeof something === "undefined") в коде.
Саймон Баумгардт-Велландер
@BenjaminGruenbaum Для ленивых программистов void 0(на этот раз) и короче, и безопаснее! Это победа в моей книге.
wizzwizz4
4
Это действительно должен быть принятый ответ. Это самый тщательный и актуальный.
Патрик
161

В JavaScript есть ноль и есть неопределенный . У них разные значения.

  • undefined означает, что значение переменной не было определено; неизвестно, какова стоимость.
  • NULL означает, что значение переменной определено и имеет значение NULL (не имеет значения).

Марин Хавербеке в своей бесплатной онлайн-книге « Красноречивый JavaScript » (выделено мной) утверждает :

Существует также аналогичное значение, нулевое, значение которого «это значение определено, но оно не имеет значения». Разница в значении между неопределенным и нулевым является в основном академической и обычно не очень интересной. В практических программах часто необходимо проверить, имеет ли что-то значение. В этих случаях может быть использовано выражение что-то == undefined, поскольку, даже если они не совпадают по значению, null == undefined приведет к значению true.

Итак, я думаю, что лучший способ проверить, было ли что-то неопределенным, было бы:

if (something == undefined)

Надеюсь это поможет!

Редактировать: в ответ на ваше редактирование свойства объекта должны работать так же.

var person = {
    name: "John",
    age: 28,
    sex: "male"
};

alert(person.name); // "John"
alert(person.fakeVariable); // undefined
Pandincus
источник
42
если (что-то == не определено) лучше написать так, как будто (что-то === не определено)
Себастьян Риттау
59
Следует отметить, что это не совсем безопасно. undefinedэто просто переменная, которая может быть переназначена пользователем: запись undefined = 'a';приведет к тому, что ваш код перестанет делать то, что вы думаете. Использование typeofлучше, а также работает с переменными (не только свойствами), которые не были объявлены.
Гейб Моутарт
7
если что-то является неопределенной глобальной переменной, (что-то == неопределенное) выдает ошибку javascript.
Морган Ченг
8
Проблема в том, что если var a = null, тогда a == undefined оценивается как true, даже если a определенно определено.
Андрей
6
Эта интерпретация комментария «Красноречивый Javascript» является обратной . Если вы действительно хотите просто проверить неопределенность, предложенный код не будет работать (он также обнаружит определенное условие, но еще не определено значение [ienull]). Нулевое значение. Предлагаемый код «if (что-то == undefined) ...» проверяет как неопределенное, так и нулевое (значение не установлено), то есть он интерпретируется как «if ((что-то не определено) ИЛИ (что-то является нулевым)) ...» Автор говорит, что часто вы действительно хотите проверить как неопределенное, так и нулевое значение.
Чак Колларс
125

Что это значит: «неопределенное свойство объекта» ?

На самом деле это может означать две совершенно разные вещи! Во-первых, это может означать свойство, которое никогда не было определено в объекте, и, во-вторых, это может означать свойство, которое имеет неопределенное значение . Давайте посмотрим на этот код:

var o = { a: undefined }

Не o.aопределено? Да! Его значение не определено. Не o.bопределено? Конечно! Нет свойства 'b' вообще! Хорошо, теперь посмотрим, как разные подходы ведут себя в обеих ситуациях:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

Мы можем ясно видеть это typeof obj.prop == 'undefined'и obj.prop === undefinedэквивалентны, и они не различают эти разные ситуации. И 'prop' in objможет обнаружить ситуацию, когда свойство вообще не было определено и не обращает внимания на значение свойства, которое может быть неопределенным.

Так что делать?

1) Вы хотите знать, является ли свойство неопределенным по первому или второму значению (наиболее типичная ситуация).

obj.prop === undefined // IMHO, see "final fight" below

2) Вы хотите просто знать, имеет ли объект какое-либо свойство и не заботиться о его значении.

'prop' in obj

Ноты:

  • Вы не можете проверить объект и его свойства одновременно. Например, это x.a === undefinedили это typeof x.a == 'undefined'повышается, ReferenceError: x is not definedесли x не определен.
  • Переменная undefinedявляется глобальной переменной (так на самом деле это window.undefinedв браузерах). Он поддерживается с ECMAScript 1st Edition, а с ECMAScript 5 - только для чтения . Так что в современных браузерах это нельзя переопределить как истинное, поскольку многие авторы любят пугать нас, но это все еще верно для старых браузеров.

Финальный бой: obj.prop === undefinedпротивtypeof obj.prop == 'undefined'

Плюсы obj.prop === undefined:

  • Это немного короче и выглядит немного красивее
  • Движок JavaScript выдаст вам ошибку, если вы ошиблись undefined

Минусы obj.prop === undefined:

  • undefined может быть переопределено в старых браузерах

Плюсы typeof obj.prop == 'undefined':

  • Это действительно универсально! Работает в новых и старых браузерах.

Минусы typeof obj.prop == 'undefined':

  • 'undefned'( опечатка ) это просто строковая константа, поэтому движок JavaScript не может помочь вам, если вы ошиблись, как я только что сделал.

Обновление (для серверного JavaScript):

Node.js поддерживает глобальную переменную undefinedкак global.undefined(ее также можно использовать без префикса 'global'). Я не знаю о других реализациях серверного JavaScript.

Константин Смолянин
источник
@ Берги спасибо за ваш комментарий. Я исправил свой ответ. В свою защиту могу сказать, что в настоящее время (по состоянию на v.0.10.18) официальная документация Node.js ничего не говорит о том, undefinedчто она является членом global. Также ни, console.log(global);ни for (var key in global) { ... }не показывает undefined в качестве члена глобальной . Но проверить, как 'undefined' in globalпоказать обратное.
Константин Смолянин,
4
Он не нуждался в дополнительной документации, так как он находится в спецификации EcmaScript , в которой также указано, что [[Enumerable]]это ложь :-)
Bergi
5
Относительно Minuses of typeof obj.prop == 'undefined'этого можно избежать, написав как typeof obj.prop == typeof undefined. Это также дает очень хорошую симметрию.
hlovdal
3
@hlovdal: Это абсолютно бессмысленно obj.prop === undefined.
Ry-
1
Когда мы верны заголовку вопроса « Обнаружение неопределенного свойства» , а не истинному (другому и гораздо более простому) вопросу в первом предложении («проверьте, если не определено ...»), вы отвечаете if ('foo' in o)… ваш ответ действительно первый правильный ответ здесь. Практически все остальные просто отвечают на это предложение.
Фрэнк Нок
70

Проблема сводится к трем случаям:

  1. Объект имеет свойство, а его значение - нет undefined.
  2. Объект имеет свойство и его значение равно undefined.
  3. У объекта нет свойства.

Это говорит нам кое-что, что я считаю важным:

Существует разница между неопределенным членом и определенным членом с неопределенным значением.

Но, к сожалению typeof obj.foo, не говорит нам, какой из трех случаев у нас есть. Однако мы можем комбинировать это с тем, "foo" in objчтобы различать случаи.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

Стоит отметить, что эти тесты одинаковы для nullзаписей тоже

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

Я бы сказал, что в некоторых случаях имеет смысл (и понятнее) проверить, присутствует ли свойство, а не проверить, является ли оно неопределенным, и единственный случай, когда эта проверка будет отличаться, - это случай 2, редкий случай фактическая запись в объекте с неопределенным значением.

Например: я только что провела рефакторинг группы кода, которая провела несколько проверок, имеет ли объект заданное свойство.

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

Что было понятнее, когда написано без проверки неопределенности.

if( "x" in blob ) { fn(blob.x); }

Но, как уже упоминалось, это не совсем то же самое (но более чем достаточно для моих нужд).

Майкл Андерсон
источник
10
Привет майкл Отличное предложение, и я думаю, что оно делает вещи чище. Однако я обнаружил, что при использовании! оператор с "в". Вы должны сказать, if (!("x" in blob)) {}с скобками во всем, потому что! Оператор имеет приоритет над «в». Надеюсь, что это помогает кому-то.
Саймон Ист
Извините Майкла, но это неверно или, по крайней мере, вводит в заблуждение в свете первоначального вопроса. «in» не является достаточным способом проверить, имеет ли свойство объекта тип неопределенного. Для доказательства, пожалуйста, смотрите эту скрипку: jsfiddle.net/CsLKJ/4
текс
2
Эти две части кода делают разные вещи! Рассмотрим и объект, заданный a = {b: undefined}; тогда typeof a.b === typeof a.c === 'undefined'но 'b' in aи !('c' in a).
mgol
3
+1. OP не дает понять, существует ли свойство и имеет ли оно значение undefined или само свойство не определено (то есть не существует).
RobG
Я бы предложил изменить точку (2.) в вашей первой таблице, { x : undefined }или, по крайней мере, добавить ее в качестве другой альтернативы (2.) в таблице - мне пришлось немного подумать, чтобы понять, что точка (2.) оценивает undefined(хотя Вы упоминаете об этом позже).
Мукахо
46
if ( typeof( something ) == "undefined") 

Это сработало для меня, а другие нет.

Kevin
источник
47
паренсы не нужны, так как typeof - оператор
aehlke
12
Но они проясняют, что проверяется. В противном случае это может быть прочитано как typeof (something == "undefined").
Абхи Бекерт,
Если вам нужны круглые скобки, то вы должны знать оператор приоритет в JS: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Ian
11
Скобки полезны именно потому, что вам НЕ нужно изучать приоритет операторов в JS, а также не нужно размышлять о том, нужно ли будущим программистам обслуживания изучать приоритет операторов в JS.
Дейв Уолли
27
Скобки полезны для разъяснения вещей. Но в этом случае они просто делают оператор похожим на функцию. Без сомнения, это проясняет намерения программиста. Но если вы не уверены в приоритетах операторов, вам лучше написать это как (typeof something) === "undefined".
Роберт,
42

Я не уверен, откуда исходит происхождение использования ===with typeof, и как соглашение я вижу, что он используется во многих библиотеках, но оператор typeof возвращает строковый литерал, и мы знаем это заранее, так почему бы вам также захотеть ввести проверить это тоже?

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string") {   // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") {    // sufficient
Эрик
источник
Отличный момент, Эрик. Есть ли снижение производительности при проверке типа?
Саймон Ист
5
@Simon: совсем наоборот - можно ожидать небольшого снижения производительности, если избегать принуждения в случае '==='. Быстрый и грязный тест показал, что '===' на 5% быстрее, чем '==' в FF5.0.1
Энтони Хэтчкинс
5
Более тщательный тест показал, что в FF IE и Chrome '==' более или менее быстрее, чем '===' (5-10%), и Opera вообще ничего не меняет
Энтони Хаткинс
3
Для использования по- ==прежнему требуется как минимум проверка типа - интерпретатор не может сравнить два операнда, не зная сначала их тип.
Альнитак,
7
==на один персонаж меньше, чем ===:)
svidgen
25

Перекрестный ответ на мой ответ по связанному вопросу Как проверить наличие «неопределенного» в JavaScript?

Специфично для этого вопроса, см. Контрольные примеры с someObject.<whatever>.


Некоторые сценарии, иллюстрирующие результаты различных ответов: 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
drzaus
источник
21

Если вы делаете

if (myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

произойдет сбой, когда переменная myvarне существует, потому что myvar не определен, поэтому скрипт не работает и тест не имеет никакого эффекта.

Поскольку объект окна имеет глобальную область видимости (объект по умолчанию) вне функции, объявление будет «прикреплено» к объекту окна.

Например:

var myvar = 'test';

Глобальная переменная myvar такая же, как window.myvar или window ['myvar']

Чтобы избежать ошибок при проверке существования глобальной переменной, лучше использовать:

if(window.myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

Вопрос, действительно ли переменная существует, не имеет значения, ее значение неверно. В противном случае глупо инициализировать переменные с неопределенным, и лучше использовать значение false для инициализации. Когда вы знаете, что все переменные, которые вы объявляете, инициализируются с помощью false, вы можете просто проверить их тип или положиться, !window.myvarчтобы проверить, имеет ли оно правильное / правильное значение. Таким образом, даже если переменная не определена, то !window.myvarто же самое для myvar = undefinedили myvar = falseили myvar = 0.

Когда вы ожидаете определенного типа, проверьте тип переменной. Чтобы ускорить тестирование состояния, вам лучше сделать:

if( !window.myvar || typeof window.myvar != 'string' )
{
    alert('var does not exists or is not type of string');
}

Когда первое и простое условие выполняется, интерпретатор пропускает следующие тесты.

Всегда лучше использовать экземпляр / объект переменной, чтобы проверить, получило ли оно допустимое значение. Это более стабильный и лучший способ программирования.

(У)

Codebeat
источник
19

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

if (obj && obj.prop) {
  // Do something;
}

Если obj или obj.prop не определены, имеют значение null или «ложь», оператор if не выполнит блок кода. Это обычно желаемое поведение в большинстве операторов блока кода (в JavaScript).

Джо Джонсон
источник
2
Если вы хотите знать, почему это работает: Javascript: логические операторы и истина / ложь
mb21
если вы хотите присвоить свойство переменной, если она определена, не ноль и не ложь, иначе используйте какое-то значение по умолчанию, вы можете использовать: var x = obj && obj.prop || 'default';
Stijn de Witt
Я полагаю, что вопрос заключается в том, чтобы явно проверить неопределенность. Ваше состояние проверяет все ложные значения JS.
NikoKyriakid
15

В статье « Изучение бездны нуля и неопределенности в JavaScript» я прочитал, что фреймворки, такие как Underscore.js, используют эту функцию:

function isUndefined(obj){
    return obj === void 0;
}
Marthijn
источник
3
void 0это всего лишь краткий способ записи undefined(так как void, за которым следует любое выражение, возвращается), он сохраняет 3 символа. Это тоже можно сделать var a; return obj === a;, но это еще один персонаж. :-)
RobG
2
voidявляется зарезервированным словом, в то время как undefinedэто не то , а undefinedравно void 0по умолчанию, вы можете присвоить значение , undefinedнапример undefined = 1234.
Брайан М. Хант
isUndefined(obj): 16 символов obj === void 0: 14 символов - сказал он.
Стейн де Витт
14

Просто что-то не определено в JavaScript, не определено , не имеет значения, является ли оно свойством внутри Object / Array или просто как переменная ...

JavaScript имеет typeofочень простое обнаружение неопределенной переменной.

Просто проверьте typeof whatever === 'undefined', вернется ли логическое значение.

Вот как isUndefined()пишется знаменитая функция в AngularJs v.1x:

function isUndefined(value) {return typeof value === 'undefined';} 

Итак, как вы видите, функция получает значение, если это значение определено, оно вернется false, в противном случае для неопределенных значений вернется true.

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

var stackoverflow = {};
stackoverflow.javascipt = 'javascript';
var today;
var self = this;
var num = 8;
var list = [1, 2, 3, 4, 5];
var y = null;

и мы проверяем их, как показано ниже, вы можете увидеть результаты перед ними в качестве комментария:

isUndefined(stackoverflow); //false
isUndefined(stackoverflow.javascipt); //false
isUndefined(today); //true
isUndefined(self); //false
isUndefined(num); //false
isUndefined(list); //false
isUndefined(y); //false
isUndefined(stackoverflow.java); //true
isUndefined(stackoverflow.php); //true
isUndefined(stackoverflow && stackoverflow.css); //true

Как вы видите, мы можем проверить что угодно, используя что-то подобное в нашем коде, как уже упоминалось, вы можете просто использовать его typeofв своем коде, но если вы используете это снова и снова, создайте функцию, подобную угловому образцу, которую я разделяю, и продолжаю использовать ее как следующий шаблон кода СУХОЙ.

Также еще одна вещь, для проверки свойства объекта в реальном приложении, в котором вы не уверены, существует ли этот объект или нет, сначала проверьте, существует ли объект.

Если вы проверите свойство объекта, а объект не существует, вы получите ошибку и остановите работу всего приложения.

isUndefined(x.css);
VM808:2 Uncaught ReferenceError: x is not defined(…)

Настолько просто, что вы можете заключить в оператор if, как показано ниже:

if(typeof x !== 'undefined') {
  //do something
}

Что также равно isDefined в Angular 1.x ...

function isDefined(value) {return typeof value !== 'undefined';}

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

Я также добавляю этот раздел из MDN, в котором есть полезная информация о typeof, undefined и void (0).

Строгое равенство и неопределенность
Вы можете использовать неопределенные операторы и операторы строгого равенства и неравенства, чтобы определить, имеет ли переменная значение. В следующем коде переменная x не определена, а оператор if оценивается как true.

var x;
if (x === undefined) {
   // these statements execute
}
else {
   // these statements do not execute
}

Примечание: здесь должен использоваться оператор строгого равенства, а не стандартный оператор равенства, потому что x == undefined также проверяет, является ли x нулевым, а строгое равенство - нет. ноль не эквивалентно неопределенному. Смотрите операторы сравнения для деталей.


Оператор Typeof и неопределенный В
качестве альтернативы можно использовать typeof:

var x;
if (typeof x === 'undefined') {
   // these statements execute
}

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

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
   // these statements execute
}

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

}

Однако этого вида техники следует избегать. JavaScript является статически ограниченным языком, поэтому, зная, объявлена ​​ли переменная, можно прочитать, проверив, объявлена ​​ли она в окружающем контексте. Единственное исключение - глобальная область, но глобальная область привязана к глобальному объекту, поэтому проверка существования переменной в глобальном контексте может быть выполнена путем проверки наличия свойства в глобальном объекте (используя оператор in, например).


Пустой оператор и неопределенный

Оператор void является третьей альтернативой.

var x;
if (x === void 0) {
   // these statements execute
}

// y has not been declared before
if (y === void 0) {
   // throws a ReferenceError (in contrast to `typeof`)
}

больше> здесь

Алиреза
источник
13

' if (window.x) {} ' безопасен от ошибок

Скорее всего, вы хотите if (window.x). Эта проверка безопасна, даже если x не был объявлен ( var x;) - браузер не выдает ошибку.

Пример: я хочу знать, поддерживает ли мой браузер History API

if (window.history) {
    history.call_some_function();
}

Как это работает:

window - это объект, который содержит все глобальные переменные в качестве своих членов, и разрешено пытаться получить доступ к несуществующему члену. Если x не был объявлен или не был установлен, то window.xвозвращает undefined . undefined приводит к ложному, когда if () оценивает его.

Deniss
источник
Но что если вы запустите в Node? typeof history != 'undefined'на самом деле работает в обеих системах.
Стейн де Витт
13

Прочитав это, я поражен, что не видел этого. Я нашел несколько алгоритмов, которые будут работать для этого.

Никогда не определен

Если значение объекта никогда не определялось, это предотвратит возврат, trueесли оно определено как nullили undefined. Это полезно, если вы хотите, чтобы true возвращалось для значений, установленных какundefined

if(obj.prop === void 0) console.log("The value has never been defined");

Определено как неопределенное или никогда не определено

Если вы хотите, чтобы это приводило trueк значениям, определенным значением undefinedили никогда не определенным, вы можете просто использовать=== undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

Определяется как ложное значение, неопределенное, нулевое или никогда не определяется.

Обычно люди просят у меня алгоритм, чтобы выяснить, является ли значение ложным undefined, или null. Следующие работы.

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}
Travis
источник
4
Я думаю, что вы можете заменить последний примерif (!obj.prop)
Stijn de Witt
@StijndeWitt, вы можете, я был довольно неопытен, когда писал это, и мой английский, кажется, был одинаково плохим, тем не менее, в ответе нет ничего неправильного
Трэвис,
3
var obj = {foo: undefined}; obj.foo === void 0-> true. Как это "никогда не определяется как undefined"? Это не верно.
Патрик Робертс
@PatrickRoberts Вы правы. Когда я написал этот ответ в феврале 2015 года (до ES6), первый вариант, который я описал, действительно работал, но сейчас он устарел.
Трэвис
10

Сравните с void 0, для краткости.

if (foo !== void 0)

Это не так многословно, как if (typeof foo !== 'undefined')

bevacqua
источник
3
Но он выдаст ReferenceError, если он fooне объявлен.
daniel1426
1
@ daniel1426: Итак, если в вашем коде есть ошибка, вы хотите скрыть ее вместо того, чтобы исправить? Не отличный подход, ИМО.
Это не используется, чтобы скрыть ошибки. Это распространенный способ определения свойств среды для определения полифилов. Например: if (typeof Promise === 'undefined') {/ * определить обещание * /}
gaperton
10

Решение неверное. В JavaScript

null == undefined

вернет true, потому что они оба «приведены» к логическому значению и являются ложными. Правильный способ будет проверить

if (something === undefined)

который является оператором идентичности ...

Рики
источник
3
Чтобы быть понятным, ===это тип равенства + (примитивное равенство | идентичность объекта), где примитивы включают строки. Я думаю, что большинство людей считают 'abab'.slice(0,2) === 'abab'.slice(2)неинтуитивным, если считать ===оператором идентичности.
Клак
1
Неправильно. Это выдает ошибку, если переменная не была создана. Не следует голосовать. Используйте вместо этого typeof.
Саймон Ист
10

Вы можете получить массив с неопределенным путем, используя следующий код.

 function getAllUndefined(object) {

        function convertPath(arr, key) {
            var path = "";
            for (var i = 1; i < arr.length; i++) {

                path += arr[i] + "->";
            }
            path += key;
            return path;
        }


        var stack = [];
        var saveUndefined= [];
        function getUndefiend(obj, key) {

            var t = typeof obj;
            switch (t) {
                case "object":
                    if (t === null) {
                        return false;
                    }
                    break;
                case "string":
                case "number":
                case "boolean":
                case "null":
                    return false;
                default:
                    return true;
            }
            stack.push(key);
            for (k in obj) {
                if (obj.hasOwnProperty(k)) {
                    v = getUndefiend(obj[k], k);
                    if (v) {
                        saveUndefined.push(convertPath(stack, k));
                    }
                }
            }
            stack.pop();

        }

        getUndefiend({
            "": object
        }, "");
        return saveUndefined;
    }

ссылка jsFiddle

Anoop
источник
Хотя это не повлияет на достоверность вашего кода, у вас есть опечатка: getUndefiendдолжно быть getUndefined.
icktoofay
8

Вот моя ситуация:

Я использую результат вызова REST. Результат должен быть проанализирован из JSON в объект JavaScript.

Есть одна ошибка, которую я должен защитить. Если аргументы для вызова rest были неверными, поскольку пользователь указал неправильные аргументы, вызов rest возвращается в основном пустым.

Используя этот пост, чтобы помочь мне защититься от этого, я попробовал это.

if( typeof restResult.data[0] === "undefined" ) { throw  "Some error"; }

В моей ситуации, если restResult.data [0] === «объект», я могу смело начинать проверку остальных членов. Если значение не определено, выведите ошибку, как указано выше.

То, что я говорю, - то, что для моей ситуации все предложения выше в этом посте не работали. Я не говорю, что я прав, а все не правы. Я вообще не мастер JavaScript, но, надеюсь, это кому-нибудь поможет.

wayneseymour
источник
Ваша typeofохрана на самом деле не защищает ни от чего, с чем не может справиться прямое сравнение. Если restResultон не определен или не объявлен, он все равно выбросит.
В вашем случае вы могли бы проще проверить, если массив пуст:if(!restResult.data.length) { throw "Some error"; }
Headbank
8

Существует хороший и элегантный способ назначить определенное свойство новой переменной, если оно определено, или назначить ему значение по умолчанию в качестве запасного, если оно не определено.

var a = obj.prop || defaultValue;

Это подходит, если у вас есть функция, которая получает дополнительное свойство конфигурации:

var yourFunction = function(config){

   this.config = config || {};
   this.yourConfigValue = config.yourConfigValue || 1;
   console.log(this.yourConfigValue);

}

Сейчас исполняю

yourFunction({yourConfigValue:2});
//=> 2

yourFunction();
//=> 1

yourFunction({otherProperty:5});
//=> 1
Мариан Клюспи
источник
7

Все ответы неполные. Это правильный способ узнать, что существует свойство, определенное как неопределенное:

var hasUndefinedProperty = function hasUndefinedProperty(obj, prop){
  return ((prop in obj) && (typeof obj[prop] == 'undefined')) ;
} ;

Пример:

var a = { b : 1, e : null } ;
a.c = a.d ;

hasUndefinedProperty(a, 'b') ; // false : b is defined as 1
hasUndefinedProperty(a, 'c') ; // true : c is defined as undefined
hasUndefinedProperty(a, 'd') ; // false : d is undefined
hasUndefinedProperty(a, 'e') ; // false : e is defined as null

// And now...
delete a.c ;
hasUndefinedProperty(a, 'c') ; // false : c is undefined

Жаль, что это был правильный ответ, похоронен в неправильных ответах> _ <

Так что, для тех, кто проходит мимо, я дам вам неопределенные бесплатно !!

var undefined ; undefined ; // undefined
({}).a ;                    // undefined
[].a ;                      // undefined
''.a ;                      // undefined
(function(){}()) ;          // undefined
void(0) ;                   // undefined
eval() ;                    // undefined
1..a ;                      // undefined
/a/.a ;                     // undefined
(true).a ;                  // undefined
Хуан Гарсия
источник
7

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

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null){
    alert('either it is undefined or value is null')
}

Если вы используете библиотеку jQuery, то jQuery.isEmptyObject()будет достаточно для обоих случаев,

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) {
    alert('Either variable:s is undefined or its value is null');
} else {
     alert('variable:s has value ' + s);
}

s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;
Красавица надар
источник
jQuery также позаботится о любых проблемах совместимости между различными браузерами с различными API-интерфейсами JavaScript.
Генри Элейн
7

Если вы используете Angular:

angular.isUndefined(obj)
angular.isUndefined(obj.prop)

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 
Виталий Федоренко
источник
2
Как добавить 1в переменную x? Нужно ли Underscore или JQuery? (Удивительно, что люди будут использовать библиотеки даже для самых элементарных операций, таких как typeofпроверка)
Stijn de Witt
6

Я использую, if (this.variable)чтобы проверить, если это определено. Простое if (variable), рекомендованное выше , для меня не получается. Оказывается, это работает только тогда, когда переменная является полем некоторого объекта, obj.someFieldчтобы проверить, определена ли она в словаре. Но мы можем использовать thisили windowкак объект словаря, поскольку любая переменная является полем в текущем окне, насколько я понимаю. Поэтому вот тест

if (this.abc) alert("defined"); else alert("undefined");

abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");

Сначала он обнаруживает, что переменная abcне определена, и определяется после инициализации.

Val
источник
5

Я предлагаю три способа для тех, кто ожидает странных ответов:

function isUndefined1(val) {
    try {
        val.a;
    } catch (e) {
        return /undefined/.test(e.message);
    }
    return false;
}
function isUndefined2(val) {
    return !val && val+'' === 'undefined';
}
function isUndefined3(val) {
    const defaultVal={};
    return ((input=defaultVal)=>input===defaultVal)(val);
}
function test(func){
    console.group(`test start :`+func.name);
    console.log(func(undefined));
    console.log(func(null));
    console.log(func(1));
    console.log(func("1"));
    console.log(func(0));
    console.log(func({}));
    console.log(func(function () { }));
    console.groupEnd();
}
test(isUndefined1);
test(isUndefined2);
test(isUndefined3);

isUndefined1:

Попробуйте получить свойство входного значения, проверьте сообщение об ошибке, если оно существует. Если входное значение не определено, сообщение об ошибке будет Uncaught TypeError: Невозможно прочитать свойство 'b' из неопределенного

isUndefined2:

Преобразуйте входное значение в строку для сравнения "undefined"и убедитесь, что это отрицательное значение.

isUndefined3:

В js необязательный параметр работает, когда входное значение точно undefined.

blackmiaool
источник
5

В ES2019 появилась новая функция - необязательная цепочка, которую вы можете использовать для использования свойства объекта, только когда объект определен следующим образом:

const userPhone = user?.contactDetails?.phone;

Он будет ссылаться на свойство телефона только тогда, когда определены user и contactDetails.

Ссылка https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Przemek Struciński
источник
Раньше я часто использовал функцию, получаемую из lodash, очень удобно для доступа к объектам такого типа, но новая необязательная цепочка покрывает большую часть использования _.get
Al Hill
4
function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Возвращает false, если переменная установлена, и true, если не определено.

Тогда используйте:

if (isUnset(var)) {
  // initialize variable here
}
Rixius
источник
5
Нет, не делай этого. Требуется только очень простой тест, чтобы доказать, что вы не можете осмысленно обернуть typeofтест в функцию. Удивительно, что 4 человека проголосовали за это. -1.
Стейн де Витт
4

Я хотел бы показать вам кое-что, что я использую для защиты undefinedпеременной:

Object.defineProperty(window, 'undefined', {});

Это запрещает кому-либо изменять window.undefinedзначение, поэтому уничтожает код на основе этой переменной. При использовании "use strict"все попытки изменить его значение будут заканчиваться ошибкой, в противном случае это будет игнорироваться.

Seti
источник
4

Вы также можете использовать Proxy, он будет работать с вложенными вызовами, но потребует одну дополнительную проверку:

function resolveUnknownProps(obj, resolveKey) {
  const handler = {
    get(target, key) {
      if (
        target[key] !== null &&
        typeof target[key] === 'object'
      ) {
        return resolveUnknownProps(target[key], resolveKey);
      } else if (!target[key]) {
        return resolveUnknownProps({ [resolveKey]: true }, resolveKey);
      }

      return target[key];
    },
  };

  return new Proxy(obj, handler);
}

const user = {}

console.log(resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else); // { isUndefined: true }

так что вы будете использовать его так:

const { isUndefined } = resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else;
if (!isUndefined) {
  // do someting
}
Саркис Арутюнян
источник