Проверка существования вложенного ключа в JavaScript объекте
Быстрый ответ
Прежде чем погрузиться в теорию, вот вам функция для проверки ключа во вложенном объекте:
const keyExists = (obj, path) => path.split('.').every(key => {
return (obj = obj?.[key]) !== undefined;
});
// Пример применения:
const obj = { a: { b: { c: 1 } } };
console.log(keyExists(obj, 'a.b.c')); // true
console.log(keyExists(obj, 'a.b.c.d')); // false
Эта функция использует split('.')
вместе с every()
, позволяя проверять ключи последовательно. Также здесь использована конструкция obj?.[key]
для безопасного доступа ко вложенным объектам.
Изучаем опциональное цепочное объединение и метод reduce
Введение в опциональное цепочное объединение
Опциональное цепочное объединение ?.
служит для проверки существования вложенных свойств без необходимости явного контроля на каждом уровне. Это усовершенствование было внесено в ECMAScript 2020 для удобства разработчиков:
// Безопасный доступ к глубоко вложенному свойству
const value = obj?.a?.b?.c; // Если путь отсутствует, вернется undefined
// Безопасный вызов метода...
const result = obj?.a?.b?.myMethod?.(); // Если метод отсутствует, вернется undefined
Используем reduce для функционального подхода
Метод reduce
позволит привнести в проверку вложенных свойств дух функционального программирования:
const nestedKeyExists = (obj, path) => path.split('.').reduce((acc, key) => acc?.[key], obj) !== undefined;
Рефакторинг с помощью lodash и изящных паттернов
Применим lodash
При работе с вложенными объектами может оказаться полезной библиотека Lodash. Метод _.get
позволяет безопасно извлечь вложенные свойства:
const _ = require('lodash');
const value = _.get(obj, 'a.b.c', 'default');
Также возможно использовать массивы для сложных путей:
// Пути в виде массивов ключей – почему бы и нет?
const value = _.get(obj, ['a', 'b', 'c'], 'default');
Применяем паттерны кодирования
Паттерн Оливера Стиля подойдет вам для изящного обращения к вложенным свойствам:
// Элегантный доступ к свойствам с использованием паттерна Оливера Стила
const value = (((obj || {}).a || {}).b || {}).c;
Осваиваем будущее с Babel
Чтобы обеспечить совместимость кода с различными браузерами и использовать современные возможности JavaScript, вы можете воспользоваться Babel:
{
"plugins": ["@babel/plugin-proposal-optional-chaining"]
}
С Babel версии 7.8.0 и выше, вы получаете возможность использовать новые возможности JavaScript, которые ещё только становятся стандартом.
Избегаем подводных камней: лучшие практики
Следуем простоте
KISS (Keep It Simple, Stupid)! Избегайте ненужно сложных конструкций и трюков (например, Reflect.has
). Лаконичность – превыше всего!
Заботимся о памяти
Контролируйте, как вы используете ссылки, и избегайте создания лишних замыканий. Размещайте ваш код логично.
Обеспечиваем совместимость с браузерами
Убедитесь, что нужные функции поддерживают вашу среду выполнения. Для этого вы можете использовать такие инструменты, как "caniuse" или таблицы совместимости Babel.
Осваиваем работу с вложенностью
Значение по умолчанию – наш страховой механизм
Укажите значение по умолчанию, чтобы избежать неопределённых значений:
const safeAccess = (obj, path) => path.split('.').reduce((acc, key) => acc ? acc[key] : {}, obj);
const defaultValue = safeAccess(obj, 'a.b.c') || 'default';
Ключи-миксы? Отличное решение!
Если ваши пути включают индексы массива или переменные ключи, адаптируйте свои функции, чтобы они учитывали разнообразные сценарии:
const isValidPath = (obj, path) => {
return path.split('.').reduce((acc, key) => {
if (acc && key in acc) return acc[key];
// Не забываем про обработку массивов и их индексов
if (Array.isArray(acc) && !isNaN(key)) return acc[key];
return undefined;
}, obj);
};
Гибкость при работе с вложенностью
Создавая функции обработки изменчивых структур данных, предусмотрите универсальное решение для различных форматов.
Визуализация
Представьте себе задачу нахождения пути в лабиринте:
Start: Entrance (🚪)
Goal: Find the Treasure Room (🏆)
Проверка наличия пути в объекте – это как поиск маршрута через лабиринт:
// Проход по лабиринту аналогичен обращению к ключам вложенного объекта
const labyrinth = {
room1: {
room2: {
treasureRoom: "🏆"
}
}
};
function hasPath(obj, path) {
return path.reduce((o, key) => (o && o[key] != null) ? o[key] : false, obj);
}
// Нет минотавра в комнатах 1 и 2, к счастью 🐂
hasPath(labyrinth, ['room1', 'room2', 'treasureRoom']); // Вернёт 🏆
Успех!
Путь найден: 🚪 ➡️ 🏆
Лабиринт покорен, сокровище у нас в руках. Время для победного танца! 🙌
Полезные материалы
- Опциональное цепочное объединение (?.) – JavaScript | MDN — MDN рассказывает об опциональном цепочном объединении.
- Проверка существования ключа во вложенном объекте JavaScript – Stack Overflow — интересные обсуждения на Stack Overflow.
- Документация Lodash — изучаем метод
get
в Lodash: извлечение вложенных свойств как ниндзя. - Опциональное цепочное объединение · V8 — подробности о нововведениях от разработчиков V8, вошедших в ECMAScript 2020.
- Опциональное цепочное объединение '?.' – javascript.info — учебник с заданиями и примерами.
- Лучшие практики JavaScript – W3C Wiki — рекомендации для написания качественного и поддерживаемого кода.
- npm: Плагин ESLint для безопасного использования опционального цепочного объединения — полезный плагин ESLint для вашего кода.