Нульова перевірка JavaScript


170

Я натрапив на такий код:

function test(data) {
    if (data != null && data !== undefined) {
        // some code here
    }
}

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


Зокрема, у цій відповіді зазначено, що

Ви отримаєте помилку, якщо отримаєте доступ до невизначеної змінної в будь-якому іншому контексті, крім typeof.

Оновлення: відповідь (цитата) вище може бути оманливою. Слід сказати «незадекларована змінна» , а не «невизначена змінна» .

Як я з'ясував, у відповідях Райана ♦ , maerics та nwellnhof , навіть коли жодним аргументом не надано функції, її змінні для аргументів завжди зазначаються. Цей факт також підтверджує неправильність першого пункту у списку нижче.


Наскільки я розумію, можливі наступні сценарії:

  • Функція викликалася без аргументів, таким чином, робиться dataневизначена змінна і виникає помилка на data != null.

  • Функція викликалася спеціально з null(або undefined), як її аргумент, і в цьому випадку data != nullвже захищає внутрішній код, роблячи && data !== undefinedмарним.

  • Функція викликалася ненульовим аргументом, і в цьому випадку вона буде тривіально передавати і data != null і, і data !== undefined .

Питання: Чи правильно я розумію?


На консолі Firefox я спробував наступне:

--
[15:31:31.057] false != null
[15:31:31.061] true
--
[15:31:37.985] false !== undefined
[15:31:37.989] true
--
[15:32:59.934] null != null
[15:32:59.937] false
--
[15:33:05.221] undefined != null
[15:33:05.225] false
--
[15:35:12.231] "" != null
[15:35:12.235] true
--
[15:35:19.214] "" !== undefined
[15:35:19.218] true

Я не можу з’ясувати випадок, коли data !== undefined після цього data != null може бути корисно.


9
Просто використовуйте if (data). Це мнемічний Javascript спосіб перевірити, чи dataзмінна оцінюється як істина. undefined, null, Брехня, 0, порожній рядок, порожній масив і (?) Об'єкт без властивостей відповідає значенню БРЕХНЯ, інше правда.
J0HN

20
@ J0HN - Використання if(data)означатиме, що він не може передавати falseабо 0як значення для data.
технофобар

@ J0HN Крім того, в тій же самій відповіді, яку я згадую, також зазначено, що:, if(typeof someUndefVar == whatever) -- worksі if(someUnderVar) -- error.
afsantos

2
Мабуть, це повинно бути data !== null && data !== undefined, що еквівалентно тому, data != nullщо рівнозначно data != undefined. Колишня форма має перевагу, оскільки вона більш чітка щодо умов, тоді як було б легко не помітити, що обидва nullта undefinedперевіряються з двома останніми умовами.
zzzzBov

2
До речі, явні тести на undefinedІМО - це кодовий запах. Це не захищене ключове слово типу null, це змінна, яка, як правило, не визначена. Це цілком дійсно і порушить ваш код:undefined = 1
Izkata

Відповіді:


106

"Не визначена змінна" відрізняється від значення undefined.

Невизначена змінна:

var a;
alert(b); // ReferenceError: b is not defined

Змінна зі значенням undefined:

var a;
alert(a); // Alerts “undefined”

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


32
data !== null && data !== undefinedЦе мало б сенс.
bfavaretto

@bfavaretto: Так, тож насправді це може бути помилка друку. Але ніколи не знаєш…: D
Ry-

1
Як я і думав, дякую за роз’яснення. Також я не думаю, що це помилка друку. Я провів пошук і підрахунок у всьому сценарії, і він виявив 10 випадків, так що ... Я думаю, автору також потрібне уточнення з цього приводу.
afsantos

2
Почеркніть мій коментар вище: насправді data != nullперевіряли б і те, nullі undefined(але, що цікаво, лише для nullта undefined, а не інші хибні значення).
bfavaretto

90

У JavaScript null- це спеціальний однотонний об'єкт, який корисний для сигналізації "немає значення". Ви можете перевірити його за допомогою порівняння, і, як зазвичай в JavaScript, це добра практика використання ===оператора, щоб уникнути плутанини примусу типу:

var a = null;
alert(a === null); // true

Як зазначає @rynah, "undefined" трохи заплутаний у JavaScript. Однак завжди безпечно перевірити, чи typeof(x)є рядок "невизначеним", навіть якщо "х" не є оголошеною змінною:

alert(typeof(x) === 'undefined'); // true

Крім того, змінні можуть мати "невизначене значення", якщо вони не ініціалізовані:

var y;
alert(typeof(y) === 'undefined'); // true

Збираючи все це разом, ваш чек повинен виглядати так:

if ((typeof(data) !== 'undefined') && (data !== null)) {
  // ...

Однак, оскільки змінна "data" завжди визначається, оскільки це формальний параметр функції, використання оператора "typeof" не є необхідним, і ви можете сміливо порівнювати безпосередньо з "undefined value".

function(data) {
  if ((data !== undefined) && (data !== null)) {
    // ...

Цей фрагмент означає, що "якщо функція викликалася аргументом, який визначений і не є нульовим ..."


5
Чому він повинен виглядати так? != nullбуде істинним для всіх значень, крім nullі undefined, і ми впевнені, що ця змінна оголошена. typeofв інших ситуаціях навіть може бути небезпечно - що робити, якщо ви неправильно введете ім’я змінної? Це може залишатися невизначеним протягом тривалого часу, оскільки помилок немає.
Ри-

@maerics Отож, якби я правильно дотримувався вашої відповіді, при нульовій перевірці, як у наведеному вище сценарії, ви б взагалі не використовували !=, лише суворе порівняння !==,?
afsantos

@rynah: Я не вважаю, що я знаю достатньо про загальне рішення ОП, щоб знати, чи підходить нульовий тест чи ні, але я змінив, щоб згадати той факт, що використання "typeof" не потрібне.
maerics

@afsantos: насправді я не думаю, що багато (будь-які?) значення перетворяться на нульові; однак найкраща практика використовувати суворе порівняння ( ===), якщо ви дійсно не знаєте, що робите, і хочете порівняння після конверсії ( ==).
maerics

1
@Izkata: Видаліть будь-яку бібліотеку, яка намагається переглянути нову форму undefined. Також Safari на iPad робитиме це ні в якому разі. Ви навіть не можете delete window.undefined.
Ри-

10

У вашому випадку використовуйте data==null(що справедливо ТОЛЬКО для нульового та невизначеного - на другому малюнку зосередьтеся на рядках / стовпцях, що мають значення null-undefined)

Тут у вас є все ( src ):

якщо

введіть тут опис зображення

== (його заперечення ! = )

введіть тут опис зображення

=== (його заперечення ! == )

введіть тут опис зображення


8

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

A: Так, dataбуде встановлено невизначений. Див. Розділ 10.5 Декларація, що зобов'язує миттєвий характер специфікації. Але доступ до невизначеного значення не викликає помилки. Ви, ймовірно, плутаєте це з доступом до незадекларованої змінної в суворому режимі, що призводить до помилки.

З: Функція викликалася спеціально з null (або невизначеною), як її аргумент, і в цьому випадку дані! = Null вже захищає внутрішній код, роблячи && data! == undefined непридатними.

З: Функція викликалася ненульовим аргументом, і в цьому випадку вона буде тривіально передавати обидва дані! = Null та data! == undefined.

A: Правильно. Зауважте, що наступні тести еквівалентні:

data != null
data != undefined
data !== null && data !== undefined

Див. Розділ 11.9.3 Алгоритм порівняння абстрактних рівностей та розділ 11.9.6 Алгоритм порівняння рівних рівностей специфікації.


Я не плутав із недекларованими змінними, я дійсно не знав, як це працює, коли аргументів не надано. Я був переконаний, що dataвзагалі не існуватиме, а не налаштований на це undefined. Я вдячний за уточнення, і ці посилання допомогли мені зрозуміти детальніше, як працюють обидві рівності.
afsantos

3

Я думаю, тестування змінних на значення, яких ви не очікуєте, взагалі не є хорошою ідеєю. Тому що тест як ваш можна розглянути як написання чорного списку заборонених значень. Але що робити, якщо ви забудете перерахувати всі заборонені значення? Хтось, навіть ви, може зламати ваш код, передаючи несподіване значення. Тому більш підходящим підходом є щось на зразок білого списку - тестування змінних лише на очікувані значення, а не несподівані. Наприклад, якщо ви очікуєте, що значення даних буде рядком замість цього:

function (data) {
  if (data != null && data !== undefined) {
    // some code here
    // but what if data === false?
    // or data === '' - empty string?
  }
}

зробити щось подібне:

function (data) {
  if (typeof data === 'string' && data.length) {
    // consume string here, it is here for sure
    // cleaner, it is obvious what type you expect
    // safer, less error prone due to implicit coercion
  } 
}

2

typeof foo === "undefined"відрізняється від foo === undefined, ніколи не плутайте їх. typeof foo === "undefined"це те, що вам справді потрібно. Також використовуйте !==замість!=

Тож заяву можна записати як

function (data) {
  if (typeof data !== "undefined" && data !== null) {
    // some code here
  }
}

Редагувати:

Не можна використовувати foo === undefinedдля недекларованих змінних.

var t1;

if(typeof t1 === "undefined")
{
  alert("cp1");
}

if(t1 === undefined)
{
  alert("cp2");
}

if(typeof t2 === "undefined")
{
  alert("cp3");
}

if(t2 === undefined) // fails as t2 is never declared
{
  alert("cp4");
}

1
Гаразд, але змінна оголошена в цьому випадку, тож у чому проблема?
Ри-

Особисто мені здається foo === undefinedнебезпечним у використанні. Це робить ваш код не в тому ж стані, який ви намагалися запобігти.

Я говорю про аргумент відповідної функції. Дивитися також мій інший коментар .
Ри-

1
Чому це заперечують? Найперше речення - це правильне та важливе розмежування!
Ізката

1
@Izkata: тому що немає пояснення для початкового твердження. foo === undefinedцілком прийнятний у ситуації з ОП (якщо припустити, що undefinedце не було відмінено). Відповідь також не дозволяє пояснити, чому його !== слід використовувати замість!= .
Метт

1

Простий спосіб зробити тест:

function (data) {
    if (data) { // check if null, undefined, empty ...
        // some code here
    }
}

5
Чи не залежить цей контекст тесту? Я маю на увазі, якщо очікуваний тип для dataрядка, цей тест повертає помилку на порожні рядки, що може бути, а може і не бути відповідним (функція може хотіти якось обробляти порожню рядок).
afsantos

5
За винятком , що якщо «дані» має значення ""чи 0або NaN(або інші) «якщо» блок буде пропущено; що може бути або не бути наміром ОП.
maerics

Вибачте @afsantos, я не побачив ваш коментар, якщо ви хочете отримати помилкові, коли дані не визначені, нульові ... за винятком випадків, коли дата порожня, вам потрібно буде створити інший var toTest = data; з іншим тестом після першого, як-от: if (toTest == "") {// якийсь код тут}
Кадірі

-5
var a;
alert(a); //Value is undefined

var b = "Volvo"; 
alert(b); //Value is Volvo

var c = null;
alert(c); //Value is null

4
Будь ласка, додайте пояснення щодо того, що це має означати.
Ри-

Це не реально перевірити на null.
user4642212
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.