JavaScript | Как обратиться к несуществующему свойству объекта и не сломать всё?

JavaScript | Как обратиться к несуществующему свойству объекта и не сломать всё?

Часто в JavaScript мы пытаемся обращаться к каким-то свойствам объектов. Часто гоняем их в массивах. Иногда мы пытаемся использовать обращения к несуществующим ключам в условиях или функциях.

И однажды возникнет такая ситуация, при которой всё сломается. Мы не специально, просто так получается. Как быть?

 

В чём проблема с ключами объектов? Что именно ломается?

Представим, что у нас есть объекты:

let car = {
  brand: 'Audi',
  color: 'Red'
}

let car2 = { 
   brand: 'BMW', 
   color: 'Black', 
   model: 'Model:X10'
}

Представим, что подобных объектов у нас в массиве около 10000. Мы пробегаем по каждому объекту в массиве и пытаемся преобразовать название марки авто.

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

Если мы сейчас попытаемся обратиться к свойству model у объекта car то нам вернётся undefined. И это правильно, потому что ключ марки автомобиля не объявлен. Значения тоже нет.

Но если мы переименовываем по шаблону все названия моделей авто, то случается это:

car.model.replace('Model:','')
Обратились к несуществующему свойству объекта в JavaScript и всё сломалось - ошибка
Обратились к несуществующему свойству объекта в JavaScript и всё сломалось — ошибка

Вывалится ошибка. Программа перестанет работать. Рухнет вообще всё т. к. в среду выполнения кода вывалилась ошибка. Что делать?

Можно, конечно, пытаться «ловить» ошибку блоком try|catch, но это громоздко и не всегда уместно.

 

Решение проблемы

В JavaScript у нас есть возможность «попытаться обратиться» к свойству объекта БЕЗОПАСНО. Оформляется это при помощи знака вопроса перед точкой:

car.model?.replace('Model:','')

В нашем случаем мы не знаем как метод replace() отреагирует на «пустые» значения по ключам model.

Поэтому мы должны оформить обращение к методу при помощи двух символов — «?.» (вопрос и точка).

Если ключ model окажется несуществующим, то мы НЕ провалимся в ошибку.

Избежали ошибки при обращении к несуществующему свойству объекта в JavaScript
Избежали ошибки при обращении к несуществующему свойству объекта в JavaScript

Пример преобразования в массиве:

// С ОШИБКОЙ

[{brand: ‘Audi’,color: ‘Red’},{brand: ‘BMW’, color: ‘Black’, model: ‘Model:X10’}, {brand: ‘Volvo’, color: ‘White’, model: ‘Model:Finne’}].map(i=>{i.model=i.model.replace(‘Model:’,»); return i})

// Без ОШИБКИ

[{brand: ‘Audi’,color: ‘Red’},{brand: ‘BMW’, color: ‘Black’, model: ‘Model:X10’}, {brand: ‘Volvo’, color: ‘White’, model: ‘Model:Finne’}].map(i=>{i.model=i.model?.replace(‘Model:’,»); return i})

Преобразовали все объекты в массиве и не упали в ОШИБКУ из-за несуществующего свойства у объекта JavaScript
Преобразовали все объекты в массиве и не упали в ОШИБКУ из-за несуществующего свойства у объекта JavaScript

Имена марок автомобилей были успешно заменены. В объектах без ключа «model» прописался этот ключ со значением undefined.

 

Информационные ссылки

Стандарт ECMAScripthttps://tc39.es/ecma262/multipage/

Раздел «13.3 Left-Hand-Side Expressions» — https://tc39.es/ecma262/#sec-left-hand-side-expressions

Производство «OptionalChain» — https://tc39.es/ecma262/#prod-OptionalChain