Skip to main content

Чому proxy швидший за defineProperty?

Сам по собі Proxy не магічно "швидший" за defineProperty на одній операції. Але в реальній архітектурі (як у Vue 3 проти Vue 2) він дозволяє виконувати набагато менше зайвої роботи, тому вся система реактивності загалом виходить швидшою і простішою.

Розберемо по кроках.


1. defineProperty: потрібно обійти весь об'єкт заздалегідь

Vue 2:

  • Щоб зробити об'єкт реактивним, потрібно пройтися по кожній властивості:

    js
    Object.defineProperty(obj, 'field', { get() { ... }, set(v) { ... } })
  • Вкладені об'єкти й масиви теж треба рекурсивно обійти і "обгорнути".

  • Великий об'єкт ⇒ вже на старті купа роботи (O(N) за кількістю полів).

Крім того:

  • Додавання нового поля не реактивне, поки його окремо не "обгорнеш".
  • Видалення властивості теж не відстежується.
  • З масивами доводиться городити костилі (перехоплювати методи push, splice тощо).

Підсумок: Багато коду, багато обходів, багато "магії".


2. Proxy: один об'єкт - одна обгортка

Vue 3:

js
const reactiveObj = new Proxy(obj, { get(target, key, receiver) { ... }, set(target, key, value, receiver) { ... }, deleteProperty(target, key) { ... }, has(target, key) { ... }, ownKeys(target) { ... } })

Що це дає:

  • Обгортаємо цілий об'єкт однією операцією, а не кожну властивість.
  • Не потрібно заздалегідь обходити всі ключі.
  • Вкладені об'єкти можна робити реактивними ліниво - лише коли до них звертаються.
  • Додавання/видалення властивостей автоматично проходить через set / deleteProperty.
  • Масиви працюють нормально: індекси, length, методи - все перехоплюється проксі-пастками без хаків.

Підсумок: Менше "підготовчої" роботи, менше спецвипадків, все прямолінійніше.


3. Чому це на практиці швидше

З defineProperty:

  • Великий об'єкт ⇒ довге початкове спостереження (observer).
  • Будь-яка зміна структури (нове поле, видалення) ⇒ проблеми або додаткові костилі.
  • Окрема логіка для масивів, для прототипів, для вкладених структур.

З Proxy:

  • Обгортка O(1) на об'єкт.
  • Немає потреби при ініціалізації проходити всю глибину.
  • Значно менше допоміжного коду й зайвих операцій.
  • JS-рушії (V8, SpiderMonkey тощо) уже добре оптимізують проксі-підхід, коли код написано передбачувано.

Тому в реалістичному застосунку (як Vue 3):

  • швидший старт (менше роботи при створенні реактивних об'єктів),
  • менше накладних витрат при роботі з великими структурами,
  • менше костилів для масивів, delete, in, for...in, Object.keys тощо.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.