Виявлення невизначеного властивості об'єкта


Відповіді:


2680

Звичайний спосіб перевірити, чи є властивість властивості особливим значенням 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`");
}

9
якщо щось є недійсним, воно визначається (як null), але ви можете об'єднати занадто великі чеки. Прикрою деталлю вищевказаного коду є те, що ви не можете визначити функцію для перевірки, добре ви можете визначити функцію ... але спробуйте її використати.
neu-rah

5
@ neu-rah, чому ти не можеш написати функцію? чому б не сталося щось подібне? Здається, це працює для мене. Чи є випадок, який я не розглядаю? jsfiddle.net/djH9N/6
Зак

7
@Zack Ваші тести на isNullorUndefined не враховували випадок, коли ви викликаєте isNullOrUndefined (f), а f - незадекларовано (тобто там, де немає декларації "var f").
pnkfelix

109
Бла, тисячі голосів зараз. Це найгірший можливий спосіб зробити це. Я сподіваюся, що перехожі побачать цей коментар і вирішать перевірити… ах… інші відповіді.
Ри-

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


133
+1 за те, що зазначив, що myVar === undefined призведе до помилки, якщо myVar не буде оголошено
Енріке

73
Я знаходжу перше виправдання, яке дається тут, за те, що я не використовую === undefinedздивування. Так, ви можете призначити це undefined, але немає законних причин для цього, і передбачувано, що це може порушити ваш код. В C ви можете #define true false, а в Python ви можете призначити Trueі False, але люди не відчувають необхідності розробляти свій код на цих мовах таким чином, щоб захистити від можливості навмисно саботувати власне середовище в іншому місці коду . Чому тут можливо розглянути можливість віднесення undefinedнавіть до вартості?
Марк Амері

19
окрім коментарів до Marks, я не розумію цього: "myVar === undefined призведе до помилки в ситуації, коли myVar не визначено". - чому це погано? Чому я не хочу мати помилку, якщо я посилаюся на незадекларовані змінні?
eis

5
Також пам’ятайте, що ви завжди можете зробити, void 0щоб отримати значення, на яке undefinedвказує. Так ви можете зробити if (myVar === void 0). 0не є спеціальним, ви можете буквально помістити будь-який вираз там.
Клавдіу

28
У сучасних браузерах (FF4 +, IE9 +, Chrome невідомо) змінити вже неможливо undefined. MDN: undefined
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. Натомість це властивість глобального об’єкта зі значенням Undefined. Однак, починаючи з ES5, ця властивість доступна лише для читання і не може бути налаштована . Жоден сучасний веб-переглядач не дозволить змінити undefinedвластивість, і станом на 2017 рік це було давно. Відсутність строгого режиму теж не впливає undefinedна поведінку людини - вона просто робить такі заявиundefined = 5 робити нічого, а не кидати. Оскільки це не ключове слово, ви можете оголосити змінні з ім'ям undefined, і ці змінні можна змінити, зробивши цей звичайний шаблон:

    (function (undefined) {
        // …
    })()

    більш небезпечним , ніж використання глобальної undefined. Якщо ви повинні бути сумісними з ES3, замінітьundefined з на void 0- не вдайтеся typeof. ( voidзавжди був унарним оператором, який оцінює значення Undefined для будь-якого операнда.)

З тим, як змінюються змінні, настав час вирішити власне питання: властивості об'єкта. Немає жодної причини використовувати typeofвластивості об'єкта. Раніше виняток щодо виявлення функцій тут не застосовується - typeofмає лише особливу поведінку щодо змінних, і вирази, які властивості посилальних об'єктів не є змінними.

Це:

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

є завжди точно еквівалент в this³:

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

і враховуючи наведені вище поради, щоб не плутати читачів з тим, чому ви користуєтесь typeof, оскільки це має найбільш сенс використовувати=== для перевірки рівності, тому що це може бути відновлене для перевірки значення змінної пізніше, і тому, що вона просто зрозуміла виглядає краще, ви завжди повинні використовувати === undefined³ і тут .

Щось ще слід враховувати, коли справа стосується властивостей об'єкта, - чи дійсно взагалі хочете перевірити undefined. Дане ім'я властивості може бути відсутнім на об'єкті (видаючи значення undefinedпри читанні), представляти на самому об'єкті зі значенням undefined, присутнє на прототипі об'єкта зі прототипами об'єкта значення на MDNundefined або бути присутнім на будь-якому з тих, хто не має undefinedзначення. 'key' in objпідкаже, чи є ключ де-небудь у ланцюзі прототипу об'єкта, і Object.prototype.hasOwnProperty.call(obj, 'key')повідомить, чи знаходиться він безпосередньо на об'єкті. Я не буду детально описуватись у цій відповіді про прототипи та використання об’єктів у якості рядкових карт, тому що це, головним чином, призначене для протидії всім поганим порадам в інших відповідях, незалежно від можливих тлумачень оригінального питання. Читайте далі більше!

¹ незвичний вибір прикладу назви змінної? це справжній мертвий код із розширення NoScript для Firefox.
² не припускаю, що взагалі нормально не знати того, що входить у сферу застосування. бонусна вразливість, викликана зловживанням динамічним розмахом: Project Zero 1225
³ вкотре припускає середовище ES5 +, що undefinedстосується undefinedвластивості глобального об'єкта. замінити void 0інакше.


@BenjaminGruenbaum Правда, але цілком оману. Будь-який контекст, який не використовується за замовчуванням, може визначити власний undefined, приховуючи типовий. Що для більшості практичних цілей має такий же ефект, як і його перезапис.
блгт

23
@blgt Це параноїчно і не має значення для будь-якого практичного. Кожен контекст може замінити console.log, перевизначити методи прототипу Array і навіть замінити підключення Function.prototype.call` та змінити кожен раз, коли ви викликаєте функцію в JavaScript. Захист від цього дуже параноїчний і досить дурний. Як я (і minitech) сказав, ви можете використовувати void 0для порівняння з невизначеним, але знову - це нерозумно і надмірно.
Бенджамін Груенбаум

19
Я б хотів, щоб я мав більше одного рішення. Це найправильніша відповідь. Я дуже хочу перестати бачити typeof something === "undefined") код.
Simon Baumgardt-Wellander

@BenjaminGruenbaum Для ледачих програмістів void 0це (раз) і коротше, і безпечніше! Це виграш у моїй книзі.
wizzwizz4

4
Це дійсно має бути прийнятою відповіддю. Це найбільш ретельний та сучасний.
Патрік

161

У JavaScript є null, а не визначено . Вони мають різні значення.

  • невизначений означає, що значення змінної не було визначено; невідомо, що таке значення.
  • null означає, що значення змінної визначено та встановлено на null (не має значення).

У своїй безкоштовній онлайн-книзі " Красномовний JavaScript " Марійн Хавербеке зазначає :

Існує також подібне значення, null, значення якого "це значення визначено, але воно не має значення". Різниця в значенні між невизначеним і нульовим здебільшого є академічною, і зазвичай не дуже цікавою. У практичних програмах часто доводиться перевіряти, чи має щось «значення». У цих випадках може бути використаний вираз щось == undefined, оскільки, незважаючи на те, що вони не є однаковим значенням, null == undefined буде створювати істину.

Тож, мабуть, найкращий спосіб перевірити, чи щось не було визначено:

if (something == undefined)

Сподіваюся, це допомагає!

Редагування: У відповідь на вашу редагування, властивості об’єкта повинні працювати однаково.

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

alert(person.name); // "John"
alert(person.fakeVariable); // undefined

42
якщо (щось == невизначено) краще писати так, ніби (щось === невизначено)
Себастьян Ріттау

59
Слід зазначити, що це не зовсім безпечно. undefinedце лише змінна, яку можна перепризначити користувачеві: написання undefined = 'a';призведе до того, що ваш код більше не буде робити те, що ви думаєте, що це робить. Використання typeofкраще, а також працює для змінних (не лише властивостей), які не були задекларовані.
Гейб Мутхарт

7
якщо щось є невизначеною глобальною змінною, (щось == undefined) викликає помилку javascript.
Морган Ченг

8
Проблема з цим полягає в тому, що якщо var a = null, то a == undefined оцінюється як true, навіть якщо a, безумовно, визначено.
Андрій

6
Таке трактування коментаря "Красномовний JavaScript" є зворотним . Якщо ви дійсно просто хочете перевірити, чи не визначено, запропонований код не працюватиме (він також виявить визначену умову, але ще не було визначено значення [ienull]). Запропонований код "if (something == undefined) ..." перевіряє як undefined та null (не встановлено значення), тобто інтерпретується як "if ((щось не визначено) OR (щось є нульовим)) ..." Автор говорить, що часто те, що вам справді хочеться, перевіряє як невизначене, так і недійсне.
Чак Колларс

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 якщо х не визначено.
  • Змінна undefinedє глобальною змінною (тому насправді вона є window.undefinedв браузерах). Він підтримується з першого видання ECMAScript, а з ECMAScript 5 - лише для читання . Тож у сучасних браузерах не можна переосмислити справжнє, оскільки багато авторів люблять нас лякати, але це все ще стосується старих браузерів.

Фінальний поєдинок: obj.prop === undefinedvstypeof 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 на стороні сервера.


@Bergi дякую за ваш коментар. Я виправив свою відповідь. На свою захист можу сказати, що в даний час (станом на v.10.10.18) офіційна документація Node.js нічого не говорить про undefinedїї члена global. Також ні, console.log(global);ні for (var key in global) { ... }не виявляється не визначеним як член глобального . Але тест, як 'undefined' in globalпоказує протилежне.
Костянтин Смолянін

4
Для цього не потрібна додаткова документація, оскільки вона є в специфікації EcmaScript , яка також говорить, що [[Enumerable]]це неправда :-)
Бергі

5
Стосовно Minuses of typeof obj.prop == 'undefined'цього можна уникнути, написавши як typeof obj.prop == typeof undefined. Це також дає дуже приємну симетрію.
hlovdal

3
@hlovdal: Це абсолютно безглуздо obj.prop === undefined.
Ри-

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).
мгol

3
+1. OP робить його ясно , чи існує властивість і має значення невизначене , або власність не визначений сам (тобто не існує).
RobG

Я б запропонував змінити точку (2.) у вашій першій таблиці { x : undefined }або хоча б додати її як іншу альтернативу (2.) у таблиці - мені довелося на мить подумати, щоб зрозуміти, що цей пункт (2.) оцінюється на undefined(хоча ви згадуєте про це пізніше).
mucaho

46
if ( typeof( something ) == "undefined") 

Це працювало для мене, поки інші цього не робили.


47
Парени не потрібні, оскільки typeof є оператором
aehlke

12
Але вони роблять зрозуміліше, що перевіряється. Інакше це може бути прочитано як typeof (something == "undefined").
Абхі Беккерт

Якщо вам потрібні круглі дужки, то вам слід вивчити пріоритет оператора в JS: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ian

11
Парентези корисні саме тому, що НЕ потрібно вивчати пріоритет оператора в JS, а також не потрібно спекулювати, чи потрібно майбутнім програмістам технічного обслуговування вивчити пріоритет оператора в JS.
DaveWalley

27
Для уточнення речей корисні парентези. Але в цьому випадку вони просто роблять оператора схожим на функцію. Без сумніву, це пояснює наміри програміста. Але якщо ви не впевнені в перевазі оператора, скоріше за все напишіть його як (typeof something) === "undefined".
Роберт

42

Я не впевнений, звідки походить використання ===з 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 взагалі не має жодних змін: jsperf.com/triple- рівний проти два рази рівний / 6
Ентоні Хетчкінс

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

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. Коли ви знаєте, що всі змінні, які ви заявляєте, ініціалізовані з помилковими, ви можете просто перевірити його тип або покластись на !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');
}

Коли перша і проста умова справжня, перекладач пропускає наступні тести.

Завжди краще використовувати примірник / об’єкт змінної, щоб перевірити, чи отримав він дійсне значення. Він більш стабільний і є кращим способом програмування.

(у)


19

Я не бачив (сподіваюсь, що я цього не пропустив), хто перевіряв об’єкт перед власністю. Отже, це найкоротший і найефективніший (хоча і не обов'язково найбільш зрозумілий):

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

Якщо obj або obj.prop не визначено, null або "Falsy", оператор if не виконає блок коду. Це , як правило , бажана поведінка в більшості заяв кодових блоків (в JavaScript).


2
Якщо ви хочете знати, чому це працює: Javascript: Логічні оператори та truthy /
falesy

якщо ви хочете призначити властивість змінній, якщо вона визначена, не null і не falsey, інакше використовувати якесь значення за замовчуванням, ви можете використовувати: var x = obj && obj.prop || 'default';
Stijn de Witt

Я вважаю, що питання полягає в тому, щоб явно перевірити не визначене. Ваш стан перевіряють проти всіх помилкових значень JS.
NikoKyriakid

15

У статті Дослідження безодні нуля та невизначеного в JavaScript я прочитав, що такі рамки, як Underscore.js, використовують цю функцію:

function isUndefined(obj){
    return obj === void 0;
}

3
void 0це лише короткий спосіб написання undefined(оскільки саме ця пустота, що супроводжується будь-яким виразом, повертається), вона зберігає 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, не визначено , не має значення, чи це властивість усередині Об'єкта / Масиву чи просто проста змінна ...

У 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у своєму коді, але якщо ви використовуєте його знову і знову, створіть функцію, як кутовий зразок, яким я поділяюсь і продовжую повторно використовувати як дотримуючись схему DRY коду.

Також ще одна річ, для перевірки властивості об’єкта в реальній програмі, в якій ви не впевнені, що навіть об’єкт існує чи ні, перевірте, чи існує об'єкт спочатку.

Якщо ви перевірите властивість на об’єкті і об'єкт не існує, викличе помилку і зупинить роботу всієї програми.

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

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

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

Що також дорівнює isDefined у кутовому 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 є нульовим, тоді як строга рівність - ні. null не є рівнозначним невизначеному. Детальніше див. У операторах порівняння.


Оператор 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, наприклад).


Недійсний оператор і невизначений

Анульований оператор - третя альтернатива.

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;) - браузер не видає помилки.

Приклад: я хочу знати, чи підтримує мій браузер API History

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

Як це працює:

window - це об'єкт, який містить усі глобальні змінні як свої члени, і юридично намагатися отримати доступ до неіснуючого члена. Якщо x не було оголошено або не було встановлено, він window.xповертається невизначеним . undefined призводить до false, якщо if () оцінює його.


Але що робити, якщо бігти в 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");
}

4
Я думаю, ви можете замінити останній прикладif (!obj.prop)
Stijn de Witt

@StijndeWitt, ви можете, я був досить недосвідчених , коли я написав це, і мій англійська , здається, було однаково погано, проте, немає нічого неправильно у відповідь
Travis

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')


3
Але він буде кидати ReferenceError, якщо він fooне визначений.
daniel1426

1
@ daniel1426: Отже, якщо у вашому коді є помилка, ви хочете приховати її, а не виправляти? Не чудовий підхід, ІМО.

Це не використовується для приховування помилок. Це загальний спосіб виявлення властивостей середовища для визначення поліфілів. Наприклад: if (typeof Promise === 'undefined') {/ * визначити Promise * /}
gaperton

10

Рішення неправильне. У JavaScript,

null == undefined

повернеться правдою, тому що обидва вони "закинуті" на булеві і помилкові. Правильним було б перевірити

if (something === undefined)

який є ідентифікатором оператора ...


3
Щоб було зрозуміло, ===це тип рівності + (примітивна рівність | ідентичність об'єкта), де примітиви включають рядки. Я думаю, що більшість людей вважають 'abab'.slice(0,2) === 'abab'.slice(2)неінтуїтивними, якщо вважати ===оператором ідентичності.
clacke

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 посилання


Незважаючи на те , що це не вплине на дійсність вашого коду, у вас є помилка: getUndefiendмає бути getUndefined.
icktoofay

8

Ось моя ситуація:

Я використовую результат дзвінка REST. Результат повинен бути проаналізований від JSON до об’єкта JavaScript.

Є одна помилка, яку мені потрібно захистити. Якщо аргументи для виклику відпочинку були помилковими, якщо користувач вказав неправильно аргументи, виклик решти повертається в основному порожнім.

Користуючись цією публікацією, щоб допомогти мені захиститись, я спробував це.

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

Для моєї ситуації, якщо restResult.data [0] === "об'єкт", я можу сміливо почати огляд решти членів. Якщо не визначено, киньте помилку, як зазначено вище.

Я говорю про те, що для моєї ситуації всі запропоновані вище пропозиції в цій публікації не спрацювали. Я не кажу, що я правий, і всі помиляються. Я взагалі не майстер JavaScript, але, сподіваюся, це комусь допоможе.


Ваш 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 API.
Генрі Хелейн

7

Якщо ви використовуєте Angular:

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

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 

2
Як додати 1змінну x? Чи потрібні підкреслення або 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не визначена, і вона визначається після ініціалізації.


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.


4
function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Повертає значення false, якщо встановлена ​​змінна, і true, якщо вона не визначена.

Потім використовуйте:

if (isUnset(var)) {
  // initialize variable here
}

5
Ні. Не робіть цього. Потрібен лише дуже простий тест, щоб довести, що ви не можете змістовно зафіксувати typeofтест у функції. Дивовижно, що 4 людини проти цього. -1.
Stijn de Witt

4

Я хотів би показати вам щось, що я використовую для захисту undefinedзмінної:

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

Це забороняє комусь змінювати window.undefinedзначення, тому знищуючи код на основі цієї змінної. Якщо використовувати "use strict", все, що намагається змінити своє значення, закінчиться помилково, інакше воно буде мовчки ігноруватися.


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
}

4

З lodash.js.

var undefined;
function isUndefined(value) {
  return value === undefined;
}

Він створює змінну LOCAL, undefinedяку ініціалізує зі значенням за замовчуванням - реальним undefined, а потім порівнює valueзі змінною undefined.


Оновлення 9.9.2019

Я знайшов lodash оновлений його реалізація. Дивіться мою проблему та код .

Щоб бути куленебезпечним, просто використовуйте:

function isUndefined(value) {
  return value === void 0;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.