Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  1. Главная
  2. Категории
  3. Языки программирования
  4. JavaScript
  5. Object.keys + map против for...in: баги с прототипами при нормализации API-данных

Object.keys + map против for...in: баги с прототипами при нормализации API-данных

Запланировано Прикреплена Закрыта Перенесена JavaScript
for...inobject.keysпрототипы
1 Сообщения 1 Постеры 5 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • hannadevH Не в сети
    hannadevH Не в сети
    hannadev
    написал отредактировано
    #1

    Нормализация данных из API часто ломается на неожиданных свойствах из прототипов. for…in тянет за собой унаследованные ключи, а Object.keys + map держит только свои. Это спасает от багов в валидации и трансформации.

    В реальном проекте API кидает объект с полями userId, name, email. Кажется, что for…in пройдется по ним чисто. Но если где-то в цепочке прототипов висит toString или valueOf - привет, лишние итерации и кривая логика. Object.keys фильтрует их на корню, map добавляет трансформацию без костылей.

    Почему for…in - это мина под нормализацией

    for…in перебирает все enumerable свойства, включая те, что притащились из прототипа. В API-данных это редко заметно на чистых объектах {}, но стоит унаследовать от Array.prototype или Object.prototype - и код фейлит. Представь: нормализуешь response.data, мапишь id в upperCase, а вместо name ловишь constructor из прототипа.

    Проблема вылазит при рефакторе, когда добавляешь полифиллы или расширяешь Object.prototype. hasOwnProperty спасает, но это boilerplate в каждом цикле. Object.keys() возвращает массив только собственных ключей - прототипы отсекаются автоматически. С map() или for…of получаешь чистую итерацию с трансформацией на лету.

    • Enumerable свойства из прототипа: for…in их подхватывает, keys() - игнорит.
    • Порядок итерации: в keys() - как в объекте, в for…in - не гарантирован.
    • Производительность: на больших объектах keys() + map быстрее for…in с проверками.
    Свойство for…in Object.keys() + map
    Собственные ключи Только с hasOwnProperty Автоматически
    Прототипы Перебирает Игнорирует
    Трансформация Ручная в цикле Через map()
    Память Минимальная + массив ключей, но оптимизировано

    Нормализация API: реальные грабли с примерами

    API возвращает { users: [{id:1, name:‘John’}, {id:2}] }. Нормализуешь в {1: {name:‘John’}, 2: {…}}. for…in по users увидит toString, если массив унаследовал прототип. Результат - лишний ключ в нормализованном объекте, валидация слетает.

    Object.keys(users).reduce((acc, id) => { acc[id] = normalizeUser(users[id]); return acc; }, {}). Здесь map заменит reduce для brevity, прототипы не лезут. В больших респонсах разница в памяти и скорости критична - for…in с hasOwnProperty тормозит на 100k свойствах.

    // Плохо: for...in
    for(let key in apiData) {
      if (apiData.hasOwnProperty(key)) {
        normalized[key.toUpperCase()] = apiData[key];
      }
    }
    
    // Хорошо: keys + map
    const normalized = Object.keys(apiData)
      .map(key => ({ [key.toUpperCase()]: apiData[key] }))
      .reduce((acc, pair) => ({...acc, ...pair}), {});
    
    • Баг #1: toString в валидации форм - поле ‘toString’ не проходит схему.
    • Баг #2: valueOf мешает числовым id при маппинге.
    • Баг #3: Расширенный прототип (lodash._) ломает всю цепочку.

    Object.entries() как альтернатива map

    Entries() дает пары [key, value] сразу - идеально для нормализации без двойного доступа obj[key]. for…in требует ручного obj[key], что на слабых девайсах жрет циклы. map над entries() - функциональный стиль без мутаций.

    В API с nested объектами entries() + flatMap рвут for…in по читаемости. Прототипы? Забудь - entries() только свои свойства. Плюс, работает с destructuring: for(const [key, val] of Object.entries(obj)).

    Метод Когда юзать Минусы
    keys() + map Простая трансформация ключей Лишний шаг для значений
    entries() Ключ-значение пары Больше памяти на массив
    for…of keys() Иммутабельность Строго JS2015+
    • Гибкость: destructuring в map(([, value]) => transform(value)).
    • С Map вместо Object: для динамических ключей из API - size() без keys().length.
    • Proxy хак: перехват ownKeys() для валидации на лету.

    Когда for…in все же прокатит - и зачем его добивать

    Редко, но бывает: дебуггинг полного прототипа или legacy код. hasOwnProperty решает 90% багов, но добавляет шум. В нормализации API это антипаттерн - данные чистые, прототипы не нужны.

    Переходи на keys()/entries() - рефактор за 5 минут, баги в прошлом. Производительность на больших payload’ах дает +70%. Остальное - итераторы под капотом и Reflect API для edge cases.

    Дальше копай Reflect.ownKeys для non-enumerable свойств или WeakMap для кэша нормализованных данных. Прототипы останутся в прошлом, код - чистым.

    1 ответ Последний ответ
    0

    Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.

    Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.

    С вашими комментариями этот пост мог бы стать ещё лучше 💗

    Зарегистрироваться Войти

    Категории

    • Главная
    • Новости
    • Фронтенд
    • Бекенд
    • Языки программирования

    Контакты

    • Сотрудничество
    • info@exlends.com

    © 2024 - 2026 ExLends, Inc. Все права защищены.

    Политика конфиденциальности
    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Войдите или зарегистрируйтесь для поиска.
    • Первое сообщение
      Последнее сообщение
    0
    • Лента
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы