компилируется...
Перейти к основному содержанию
Рекомендовать во Вконтакте Рекомендовать в Фейсбуке Рекомендовать в Твиттере

Понимание Null и Undefined в JavaScript

Многие Javascript разработчики, как младшие, так и старшие, часто не понимают, что такое null и undefined типы. Недопонимание этих двух типов может привести к серьёзным ошибкам и обернётся часами потраченного впустую времени в виде дебага.

Прежде чем углубляться в тему, давайте сначала рассмотрим основы:

undefined

undefined возвращается, если переменная была объявлена, но значение переменной не было установлено.
Например:

let test;

В логе мы видим undefined:

log(test); // undefined

undefined также может возникнуть, если свойство объекта не существует.

let person = {
 age: 33
};

log(person.name);
// undefined

или функция имеет отсутствующий параметр:

function getAccountDetails(a) {
 console.log(a);
}

getAccountDetails();
// undefined

undefined - примитивный тип данных в Javascript:

Boolean
Undefined
Number
String
Symbol

let test
typeof test
// undefined

Проверить тип можно с помощью ключевого слова typeof:

if (typeof test ===  'undefined') {
// ...
}

undefined может быть задан явно:

let test = undefined;
console.log(test);
// undefined

test = 15;
console.log(test);
// 90

Null

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

let test = null;
console.log(test);
// null

Схожие черты

Давайте посмотрим на их сходства.

И то, и другое - это ложные (false) значения.

null и undefined типы всегда преобразуется в значение false. Они относятся к числу ложных значений в JS:

  • null
  • undefined
  • false
  • 0
  • Пустая строка -> ""
  • NaN

Если они находятся в условии оператора if-else, оператор else всегда будет выполняться:

if (null) {
 console.log('Да');
} else {
 console.log('Нет');
}

Вышеприведенное выведет Нет.

if (undefined) {
 console.log('Да');
} else {
 console.log('Нет');
}

также выведет Нет.

Оба являются примитивными значениями

В Javascript есть сложные и примитивные типы данных, null и undefined - среди примитивных типов данных:

  • null
  • undefined
  • Symbol
  • String
  • Number
  • Boolean

Примитивные типы данных обрабатываются по значению.

Различия

null и undefined означают нет значения, но имееют разные значения в определении типа:

console.log(typeof null);
// object

console.log(typeof undefined);
// undefined

Вы ожидали, что тип null вернет "null"? Правда? Это ошибка в JS существует уже на протяжении почти двух десятилетий, но дело в том, что она не может быть исправлена. Потому, что тысячи сайтов зависят от такого неправильного поведения, исправление которого приведет к их поломке.

null - это назначаемое значение, т.е. должно быть явно назначено программистом. Если переменная не назначена, она становится undefined:

let test = null;
let account; // undefined

в отличие от undefined, которые могут быть явно назначены или не назначены:

let test = undefined;
let user; 
console.log(test);
// undefined
console.log(user);
// undefined

Тесты для null

Как мы уже видели, undefined преобразовывается в "undefined", а null преобразовывается в "object".

Мы можем легко проверить на undefined:

let test;

if (typeof test === 'undefined') {
 // ...
}

Для null, мы не можем этого сделать:

let test = null;

if (typeof test === 'null') {
 // ...
}

typeof null возвращает "object", и у нас может возникнуть соблазн переписать все вышеперечисленное следующим образом:

let test = null;

if (typeof test === 'object') {
 // ...
}

Но многие сложные типы данных возвращают объекты, тип может быть проверен через typeof:

let obj = {};
let arr = [];

class Account {
};

const account = new Account(); 

console.log(typeof obj);
// object
console.log(typeof arr);
// object
console.log(typeof account);
// object

Таким образом, он не сработает, потому что массив или объект может быть значением test. Теперь, как правильно проверить на null, поскольку null - это значение false, мы объединим его проверку с проверкой на тип.

let test = null;

if (!test && typeof test === 'object') {
 // ...
}

Давайте посмотрим, что происходит, когда строгое и не строгое равенство выполняется для обоих типов.

Сравнение равенств

Не строгое сравнение:

  • Если x равен null, а y undefined, возвращается true.
  • Если x undefined, а y равен null, возвращается true.
console.log(null == undefined);
// true
console.log(undefined == null);
// true

Строгое сравнение:

Сравнение x === y, где x и y являются значениями, дает true или false. Такое сравнение выполняется следующим образом:

  1. Если тип(x) отличается от типа(y), то возвращается false.
  2. Если тип(x) равно Number, то:
    • Если x - NaN, возвращается false
    • Если y - NaN, то возвращайтся false.
    • Если x равно значению того же числа, что и y, то возвращается true
    • Если x равно +0, а y равно -0, то возвращается true
    • Если x равно -0, а y равно +0, то возвращается true

Итак, в случае:

null === undefined

Здесь будет false, потому что типы являются object и undefined, видно, что они разные, поэтому возвращается false.

console.log(null === undefined);

Далее:

null !== undefined

будет false. Почему? Потому, что null => object не тот же тип, что и undefined => undefined.

Поймите, оператор !== спрашивает, не строго ли совпадает x c y? Итак, в нашем случае да (true) объект x (null => object) не является строго равным y (undefined => undefined).

null != undefined

Тут проверяется, не совпадает ли x с y. В данном случае нет (возвращает false), так как они равны, потому что Javascript возвращает true, если x является либо null, либо undefined и y является либо null, либо undefined.

Передача null и undefined в качестве аргумента функции

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

function testFunc(name = 'test_name') {
 return name;
}

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

console.log(testFunc());
// test_name

Можно сказать так, когда имя аргумента не определено, он принимает значение test_name. Так что если мы передадим неопределенное значение в testFunc имя будет test_name:

let name;
console.log(testFunc(name));
// test_name

А что будет, если мы перейдем в функцию null? Как вы думаете, он будет выводить test_name, потому что null означает отсутствие значения, или он будет записывать null, потому что null - это значение? Посмотрим:

console.log(testFunc(null));
// null

Ничего себе! Вывелось null. Должно быть, потому что null - это object. Я бы сказал, пустой объект, но все же представляющий собой отсутствие значения.

Если вы пытаетесь проверить на null аргумент, помните, так лучше не делать:

function testFunc(name = 'test_name') {
 if (typeof name == 'null') {
  return 'test_name';
 }
 
 return name;
}

Делайте так:

function testFunc(name = 'test_name') {
 if (!name && typeof name == 'object') {
  return 'test_name';
 }
 
 return name;
}

или вы можете делегировать функции проверку на null:

function isNull(val) {
  return !val && typeof val == 'object;
}

вы можете использовать функцию isNull в любом месте вашей программы:

function testFunc(name = 'test_name') {
 if (isNull(name)) {
  return 'test_name';
 }
 
 return name;
}

Заключение

Я думаю, мы четко видим различия и сходства между null и undefined. Так что когда в следующий раз вы увидите эту ошибку, вы будете знать, что делать.

Комментарии

Пока что нет комментариев, вы можете быть первым.
Войти или Регистрация , чтобы оставлять комментарии.

Лучшие публикации

Популярные теги

Наш сайт использует куки. Узнайте больше о нашем использовании куки: политика в отношении файлов cookie
Наш сайт существует только благодаря показу онлайн-рекламы нашим посетителям.
Пожалуйста, поддержите нас, отключив блокировку рекламы.