От автора: в JavaScript есть 2 вида типов: примитивы (строки, логические значения, числа, символы) и объекты.
Объекты — это сложные структуры данных. Самый простой объект в JavaScript — это простой объект — набор ключей и связанных значений:
1 2 3 |
let myObject = { name: 'Eric Cartman' }; |
Но бывают ситуации, когда объект не может быть создан. Для таких случаев JavaScript предоставляет специальное значение null, которое указывает на отсутствующий объект.
1 |
let myObject = null; |
В этом посте вы узнаете все о null в JavaScript: его значении, как его обнаружить, разницу между null и undefined и почему широкое использование null создает трудности с обслуживанием кода.
1. Концепция null
Спецификация указывает следующее: Null — примитивное значение, которое представляет собой намеренное отсутствие какого-либо значения объекта.
Если вы видите null (присвоенное переменной или возвращенное функцией), то в этом месте должен быть объект, но по какой-то причине объект не был создан. Например, функция greetObject() создает объекты, но также может возвращать null, когда объект не может быть создан:
1 2 3 4 5 6 7 8 |
function greetObject(who) { if (!who) { return null; } return { message: `Hello, ${who}!` }; } greetObject('Eric'); // => { message: 'Hello, Eric!' } greetObject(); // => null |
При вызове функции со строковым аргументом greetObject(‘Eric’), как и ожидалось, функция возвращает объект { message: ‘Hello, Eric!’ }.
Однако при вызове функции без аргументов — greetObject() — функция возвращается null. Возврат null является разумным, потому что параметр who не имеет значения и объект не может быть создан.
1.1 Аналогия null
Думая об аналогии в реальном мире, вы можете представить переменную как коробку. Так же, как переменная может содержать объект, коробка может содержать объекты, например, чайник.
Но когда вы получаете коробку и открываете ее… а там ничего ! Кто-то ошибся и отправил вам пустую коробку. Коробка ничего не содержит, или, иначе говоря, содержит значение null.
2. Как проверить на null
Хороший способ проверить null, это — использовать оператор строгого равенства:
1 2 3 4 5 |
const missingObject = null; const existingObject = { message: 'Hello!' }; missingObject === null; // => true existingObject === null; // => false |
missingObject === null оценивается true, потому что переменная missingObject содержит значение null. Если переменная содержит ненулевое значение, например объект, выражение existingObject === null оценивается, как false.
2.1 null — ложно
Null, наряду с false, 0, », undefined, NaN, является ложным значением. Если в условных выражениях встречается ложное значение, то JavaScript приравнивает ложное значение к false.
1 2 3 4 5 6 7 |
Boolean(null); // => false if (null) { console.log('null is truthy'); } else { console.log('null is falsy'); // logs 'null is falsy' } |
2.2 typeof null
Оператор typeof value определяет тип значения. Например, typeof 15 будет ‘number’ и typeof { prop: ‘Value’ }оценивается, как ‘object’. Интересно, как оценивается type null?
1 |
typeof null; // => 'object' |
Хм… как можно оценить тип несуществующего объекта, как ‘object’ ? Оказывается, typeof null, дающее ‘object’, было ошибкой в ранней реализации JavaScript.
Не используйте оператор typeof для определения значения null. Как упоминалось ранее, используйте оператор строгого равенства myVar === null.
Если вы хотите проверить, содержит ли переменная объект с помощью оператора typeof, вы также должны проверить снова null:
1 2 3 4 5 6 7 |
function isObject(object) { return typeof object === 'object' && object !== null; } isObject({ prop: 'Value' }); // => true isObject(15); // => false isObject(null); // => false |
3. Ловушка для null
Null может появиться, часто неожиданно, в ситуациях, когда вы ожидаете объект. Затем, если вы попытаетесь извлечь свойство из null, JavaScript выдает ошибку.
Давайте снова воспользуемся функцией greetObject() и попробуем получить доступ к свойству message из возвращенного объекта:
1 2 3 4 |
let who = ''; greetObject(who).message; // throws "TypeError: greetObject() is null" |
Поскольку переменная who является пустой строкой, функция возвращает null. При доступе к свойству message из null выдается ошибка TypeError. Вы можете обработать null, используя опциональную цепочку с нулевым объединением:
1 2 3 4 |
let who = ''; greetObject(who)?.message ?? 'Hello, Stranger!'; // => 'Hello, Stranger!' |
или используйте 2 альтернативы, описанные в следующем разделе.
4. Альтернативы null
Заманчиво вернуть null, когда вы не можете построить объект. Но у этой практики есть и недостатки. Когда null появляется в вашем стеке выполнения, вы всегда должны его проверять. Я стараюсь не возвращать null, а вместо этого:
возвращать объект по умолчанию
выдавать ошибку вместо возврата null
Вспомним функцию greetObject(), возвращающую объекты приветствия. Вместо возврата null при отсутствии аргумента вы можете вернуть объект по умолчанию:
1 2 3 4 5 6 7 8 9 |
function greetObject(who) { if (!who) { who = 'Stranger'; } return { message: `Hello, ${who}!` }; } greetObject('Eric'); // => { message: 'Hello, Eric!' } greetObject(); // => { message: 'Hello, Stranger!' } |
либо вывести ошибку:
1 2 3 4 5 6 7 8 9 |
function greetObject(who) { if (!who) { throw new Error('"who" argument is missing'); } return { message: `Hello, ${who}!` }; } greetObject('Eric'); // => { message: 'Hello, Eric!' } greetObject(); // => throws an error |
Эти практики позволяют вам вообще избежать проблем с null.
5. null и undefined
undefined — значение неинициализированной переменной или свойства объекта. Например, если вы объявляете переменную без присвоения начального значения, доступ к такой переменной оценивается как undefined:
1 2 3 |
let myVariable; myVariable; // => undefined |
Основное различие между null и undefined заключается в том, что null представляет отсутствующий объект, а undefined представляет неинициализированное состояние. Оператор строгого равенства === отличает null от undefined:
1 |
null === undefined; // => false |
В то время как оператор произвольного равенства == считает null и undefined равными:
1 |
null == undefined; // => true |
Я использую оператор свободного равенства, чтобы проверить, является ли переменная null или undefined:
1 2 3 4 5 6 7 8 |
function isEmpty(value) { return value == null; } isEmpty(42); // => false isEmpty({ prop: 'Value' }); // => false isEmpty(null); // => true isEmpty(undefined); // => true |
6. Заключение
null — это специальное значение в JavaScript, которое представляет отсутствующий объект. Оператор строгого равенства определяет, является ли null переменной: variable === null. Оператор typoef полезен для определения типа переменной (число, строка, логическое значение). Однако typeof вводит в заблуждение в случае null: typeof null оценивается, как ‘object’.
Null и undefined в какой-то мере эквивалентны, тем не менее, null представляют собой отсутствующий объект, а undefined неинициализированное состояние.
По возможности избегайте возврата null или установки для переменных null. Такая практика приводит к распространению значений null и проверок на null. Вместо этого попробуйте использовать объекты со свойствами по умолчанию или даже выдавать ошибки.
Какое условие вы используете для проверки null?
Автор: Dmitri Pavlutin
Источник: dmitripavlutin.com
Редакция: Команда webformyself.