Перейти к содержимому

Стрелочые функии в JS. (user => user.age >= 18) (user && user.age >= 18) (user?.age ?? 0)

Вот пример функии:

// users.js

export const filterAdults = (users) => {

  return users.filter(user => user.age >= 18);

};

Как ее переписать чтобы обрабатывался аргумент пустая строка.

В вашем примере функция filterAdults ожидает массив объектов, но если в неё передать пустую строку (или null), JavaScript выдаст ошибку TypeError: users.filter is not a function. Это происходит потому, что у строк нет метода .filter().

Вот как можно переписать эту функцию, чтобы она была надежной («пуленепробиваемой»).


1. Простой способ (Проверка на наличие)

Самый быстрый вариант — проверить, существует ли users и является ли он массивом.

JavaScript

export const filterAdults = (users) => {
  // Если users — пустая строка, null или не массив, возвращаем пустой массив
  if (!Array.isArray(users)) {
    return [];
  }

  return users.filter(user => user && user.age >= 18);
};

2. Современный способ (Значение по умолчанию)

Если вы хотите защититься только от undefined, можно задать значение по умолчанию. Но для пустой строки это не сработает, поэтому лучше комбинировать подходы:

JavaScript

export const filterAdults = (users = []) => {
  // Проверяем, что пришел именно массив
  if (!Array.isArray(users)) return [];

  return users.filter(user => user?.age >= 18);
};

Здесь user?.age (optional chaining) защищает от ситуации, если внутри массива вместо объекта окажется null.


Почему это важно? (Логика обработки)

При написании функций важно понимать, что именно должна возвращать функция в случае некорректных данных. Обычно лучше возвращать пустой массив [], чем null или ошибку, чтобы остальной код (например, цикл в React) не сломался.


3. Профессиональный подход (Guard Clauses)

В большой разработке используют так называемые «защитные условия» (Guard Clauses) в начале функции. Это делает код чище, так как основная логика не прячется внутри if/else.

JavaScript

export const filterAdults = (users) => {
  // 1. "Вышибаем" плохие данные сразу
  const isInvalid = !users || !Array.isArray(users);
  if (isInvalid) return [];

  // 2. Спокойно работаем с данными, зная, что это массив
  return users.filter(user => {
    // Дополнительная проверка: есть ли у пользователя поле age
    return typeof user.age === 'number' && user.age >= 18;
  });
};

Что изменилось:

  • Безопасность: Функция больше никогда не вызовет «падение» программы.
  • Предсказуемость: Она всегда возвращает массив (либо с данными, либо пустой).
  • Гибкость: Мы добавили проверку typeof user.age, чтобы строки или случайные объекты не испортили результат.


Я не понимаю как прочитать «user?.age» и как это все же работает ?

Сравнение «Раньше» и «Сейчас»

Что проверяемРаньше (ES5/ES6)Сейчас (ES2020+)
Безопасный доступuser && user.ageuser?.age
Значение по умолчаниюuser.age !== undefined ? user.age : 0user?.age ?? 0

Итог

Современный вариант user?.age >= 18 делает ровно то же самое, что и длинный if (user != null && user.age >= 18), но под капотом. JavaScript сам берет на себя рутину по проверке на null и undefined.

1. Как работает user && user.age

Этот оператор проверяет «правдивость» (truthiness) левой части.

  • Если user это любая «ложь» (null, undefined, 0, false, ""), то выполнение прервется и вернется это самое «ложное» значение.
  • В чем проблема: Если user будет равен, например, числу 0, то проверка 0 && 0.age остановится на нуле, хотя технически у числа тоже можно пытаться вызвать свойства (хоть это и бессмысленно).

2. Как работает user?.age (Optional Chaining)

Этот оператор строже. Он проверяет только на «пустоту»: null или undefined.

  • Если user — это 0, false или "" (пустая строка), оператор ?. не остановится. Он посчитает, что объект существует, и попытается найти у него .age.

Наглядное сравнение на примерах

Представь, что в переменную user попало что-то странное:

Значение useruser && user.ageuser?.ageРазница
{ age: 20 }2020Одинаково
nullnullundefinedОдинаково (оба «ложные»)
undefinedundefinedundefinedОдинаково
0 (число)0Ошибка!Разница!

нет сокращения для «ИЛИ» user || user.age