Object.entries + fromEntries vs for: трансформация объектов фильтрами в поиске товаров
-
Часто в динамическом поиске товаров нужно фильтровать объект параметров - цена, категория, бренд. Классический for…in тянет прототипы и морочит голову. А Object.entries() + fromEntries() дают чистый массив пар ключ-значение, чтобы крутить фильтры через array methods без костылей.
Это ускорит код, уберет утечки в итерациях и сделает его читаемым. Разберем на примере каталога товаров, где объект фильтров трансформируется под ввод юзера. Проблема знакомая: мидлы пишут циклы, а бандл раздувается от лишних проверок.
Почему for…in - это легаси-ловушка
Код с for…in кажется простым, но под капотом он шарит по прототипам. В объекте фильтров товаров {price: {min: 100}, category: ‘electronics’} цикл потянет toString, hasOwnProperty и прочий мусор. В итоге - лишние if (obj.hasOwnProperty(key)), которые забывают. А в большом проекте это баги на прототипах.
Object.entries() режет только own свойства в массив [[‘price’, {min:100}], [‘category’, ‘electronics’]]. Фильтры на array methods - filter, map - летят без тормозов. fromEntries() собирает обратно в объект. В динамическом поиске это идеал: ввел ‘cheap’ - отфильтровал price, собрал новый объект.
- Прототипный мусор: for…in тянет Object.prototype, entries() - нет.
- Array methods: filter(([key, value]) => …) работает на ура, for требует деструкцию вручную.
- Производительность: entries/fromEntries быстрее в V8 для трансформаций, for - для простого перебора.
Сравнение for…in entries + fromEntries Прототипы Тянет Игнорирует Фильтры if внутри Array.filter() Читаемость Средне Высокая Бандл Минимум Минимум (нативно) Фильтрация по цене: entries в деле
Представь объект filters = {minPrice: 500, maxPrice: 2000, brand: ‘Samsung’}. Юзер ввел ‘expensive’ - нужно поднять minPrice до 1500. С Object.entries(filters) получаем массив, мапим price-значения, fromEntries() - назад в объект. Без мутаций, чисто функционально.
В цикле for пришлось бы obj[key] = newValue с проверками типов. А здесь chain: entries -> map -> fromEntries. В поиске товаров это трансформирует фильтры под слайдер цены или debounce-input. Нюанс: дубли ключей в fromEntries перезаписываются последним - полезно для merge.
const filters = {minPrice: 500, maxPrice: 2000, brand: 'Samsung'}; const expensiveFilters = Object.fromEntries( Object.entries(filters).map(([key, value]) => { if (key.includes('Price')) { return [key, {min: 1500, max: value.max || 5000}]; } return [key, value]; }) ); // {minPrice: {min:1500, max:2000}, maxPrice: {min:1500, max:5000? wait no}, brand: 'Samsung'}- Шаг 1: entries() -> [[‘minPrice’,500], …]
- Шаг 2: map с условием на key.startsWith(‘min’)
- Шаг 3: fromEntries() -> новый объект без мутаций.
- Бонус: Добавь .filter(([key]) => !key.startsWith(‘ignore’)) для удаления полей.
Динамический поиск по категориям и брендам
В каталоге товаров объект {category: ‘phones’, brand: [‘Samsung’,‘Apple’], inStock: true}. Поиск ‘laptops’ - нужно обновить category, добавить rating > 4. entries() разворачивает в массив, где легко фильтровать бренды или мержить новые.
С for пришлось бы nested if для каждого типа. А chain entries.filter/map/fromEntries - универсал. Для debounce-поиска это цепочка: userInput -> match -> transform key/value -> новый объект. Внимание: символы-ключей сохраняются через fromEntries, строки только entries().
const searchFilters = { category: 'phones', brands: ['Samsung'], rating: {min: 3} }; const laptopFilters = Object.fromEntries( Object.entries(searchFilters) .filter(([key]) => key !== 'brands') // убираем старые бренды .map(([key, val]) => { if (key === 'category') return [key, 'laptops']; if (key === 'rating') return [key, {min: 4}]; return [key, val]; }) );- Фильтр ключей: .filter(([key]) => key !== ‘temp’)
- Трансформ значений: map с деструкцией
- Мерж с дефолтами: entries(defaults).concat(newPairs) -> fromEntries
Задача for…in код строк entries chain код строк Фильтр price 8-10 4-5 Обновить category 6 3 Мерж объектов 12+ 5 Трансформация множественных фильтров в цепочке
Сложный кейс: объект с nested {priceRange: {min,max}, tags: []}. Динамический ввод ‘tag:premium’ - распарсить, добавить в tags. entries() + array extras (flatMap?) + fromEntries - идеально. Цикл бы утонул в if/else.
Это масштабируется на API-запросы: трансформируй filters в query params. В React/Vue state updater - чистый reducer. Грабли: fromEntries не клонирует глубоко nested, используй structuredClone если надо.
const complexFilters = { priceRange: {min: 100, max: 1000}, tags: ['new'], stock: true }; const premiumFilters = Object.fromEntries( Object.entries(complexFilters).flatMap(([key, val]) => { if (key === 'tags') { return [['tags', [...val, 'premium']]]; } return [[key, val]]; }) );- Nested update: flatMap для добавления пар
- Удаление: .filter перед map
- Валидация: map с try/catch на value
Масштаб на реальный магазинный поиск
Когда фильтров 10+ (цвет, размер, доставка), chain entries/fromEntries - спасение от boilerplate. Добавь reduce для custom logic. Циклы хороши для side-effects, но трансформы - нативно.
Под капотом V8 оптимизирует array methods лучше, чем for с объектами. В продакшене это меньше памяти в ивент-лупе. Осталось: polyfill для старых браузеров, но в 2026 - не актуал.
Когда брать for: Простой перебор без трансформа. Entries chain: Любые фильтры/мапы. Тестируй на 1000 items - разница в ms, но код чище в 2x.
Итог под hood: выбирай по задаче
Entries + fromEntries выигрывают в 80% трансформаций объектов - короче, быстрее, без прототипов. For держи для raw итераций. В поиске товаров это решает debounce, слайдеры, мержи.
За кадром - комбо с Map/Set для уникальных ключей или Lodash без него. Подумай, как впихнуть в твой state manager без лишних deps.
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.