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

for...in против Object.keys + for...of: почему прототипы ломают валидацию формы

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

    for…in и Object.keys() + for…of кажутся похожими способами пройтись по свойствам объекта. Но первый тащит за собой прототипы, а второй - чисто свои ключи. В валидации форм это выливается в баги: проверяешь поля, а вместо них ловишь toString из прототипа.

    Разница критична в реальном коде. for…in перебирает все enumerable свойства, включая унаследованные. Object.keys() фильтрует только собственные. Без hasOwnProperty или современного подхода форма валидируется криво, пропуская ошибки или фейля лишнее.

    Как for…in подцепляет прототипы

    Цикл for…in идет по всем перечисляемым свойствам объекта, включая те, что висят в цепочке прототипов. Представь типичный случай: валидация формы, где объект полей расширяет какой-то базовый Validator. Прототип несет методы вроде isValid, toString, valueOf - все они enumerable по умолчанию.

    В цикле ты ожидаешь только name, email, age. А получаешь их плюс прототипный мусор. Без проверки hasOwnProperty(key) код сломается: вместо валидации полей начнет ковырять методы, которые не предназначены для этого. Современные движки вроде V8 перебирают в порядке создания, но порядок - не спасение от лишних свойств.

    Это классическая грабля для мидлов: пишут валидатор, тестируют на пустом объекте - работает. Добавляют прототип - и привет, утечка логики.

    • Enumerable свойства прототипа участвуют всегда: toString из Object.prototype попадет в цикл, если не фильтровать.
    • Порядок не гарантирован: сначала числовые ключи по возрастанию, потом строковые по созданию - но прототипы мешаются.
    • Символьные ключи игнорируются: for…in работает только со строками, Symbols пропускает.
    Свойство for…in Object.keys()
    Собственные свойства Да Да
    Прототипные свойства Да Нет
    Порядок Сортировка числовых + хронология строк Хронология создания
    Символы Игнор Только строковые

    Object.keys() + for…of: чистый перебор без костылей

    Object.keys() возвращает массив только собственных enumerable свойств. Дальше for…of бежит по нему - никаких прототипов, никакой грязи. В валидации это идеал: проверяешь ровно те поля, что добавил сам.

    Пример: форма с полями userData = {name: ‘’, email: ‘invalid’, age: 150}. Цикл по Object.keys(userData) увидит только эти трое. Никаких toString или hasOwnProperty из прототипа. Производительность? keys() создает массив - да, но для форм это копейки, а предсказуемость бесценна.

    Сравни с for…in + hasOwnProperty: тот же эффект, но boilerplate. А for…of на entries() дает сразу ключ-значение: for (const [key, value] of Object.entries(obj)). Чисто, современно, без var.

    • Только собственные ключи: прототипы отсекаются на старте, hasOwnProperty не нужен.
    • Итерируемость: for…of работает с массивом, порядок как в объекте.
    • Entries для пар: Object.entries() - для ключ-значение без лишних обращений obj[key].
    // Плохо: for...in с прототипами
    const validatorProto = { isValid() { return true; } };
    const formData = Object.create(validatorProto);
    formData.name = '';
    
    for (let key in formData) {
      console.log(key); // name, isValid - мусор!
    }
    
    // Хорошо: Object.keys + for...of
    const cleanKeys = Object.keys(formData); // ['name']
    for (const key of cleanKeys) {
      validateField(formData[key]);
    }
    

    Валидация формы: реальный краш-код

    Возьми типичную задачу: проверить все поля формы перед сабмитом. Поля - объект {email, password, age}. Добавь прототип с методами валидации - и for…in словит их, пытаясь провалить toString как email.

    Без фильтра код выглядит innocently: for (key in formData) { if (!isValid(formData[key])) errors[key] = msg; }. Добавь прототип - и errors заполнится фигней вроде errors.toString = ‘not a string’. Форма не сабмитится по ложным ошибкам.

    Object.keys() решает: только реальные поля. Плюс в валидации учти типы ошибок: valueMissing, typeMismatch, patternMismatch - стандартные от HTML5, но в кастоме их эмулируй на своих полях.

    Таблица сравнения на примере формы:

    Подход Поля Прототип Ошибки в валидации
    for…in name, email toString, valueOf Ложные срабатывания
    Object.keys() + for…of name, email Нет Только поля формы
    for…in + hasOwnProperty name, email Отфильтровано Работает, но verbose
    • Стандартные ошибки: valueMissing для пустых, typeMismatch для email без @.
    • Кастом валидация: проверяй length, pattern - но только на своих ключах.
    • Производительность: для 10 полей разница в памяти negligible, предсказуемость рулит.

    Когда for…in все-таки юзать (редко)

    for…in не мусор полностью. Полезен для introspection: проверить наличие свойств в объекте с прототипами или копировать shallow без lodash. Но в валидации? Забудь.

    Если объект чистый, без прототипов - ок. Но реальный код редко такой. Лучше привыкнуть к Object.keys() - меньше багов, меньше if’ов.

    Не полагайся на legacy-трюки

    hasOwnProperty спасает for…in, но зачем boilerplate, когда Object.keys() решает чище? Подумай о destructuring или entries() - они еще гибче. А если форма большая, вынеси валидацию в WeakMap или Proxy - прототипы не проблема.

    В рефакторе увидишь: половина багов в формах от for…in. Перепиши на keys() + of - и спи спокойно. Осталось копнуть в итераторы глубже или Proxy для валидации on-the-fly.

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

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

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

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

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

    Категории

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

    Контакты

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

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

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

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

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