Mastering JavaScript Proxy and Reflect: Deep Dive into Vue 3 Reactivity

This article explains how Vue 3 replaces Vue 2’s Object.defineProperty reactivity with JavaScript’s Proxy, covering Proxy fundamentals, handler traps, the relationship with Reflect, internal methods and slots, and the distinction between ordinary and exotic objects, providing code examples and visual diagrams.

WeDoctor Frontend Technology
WeDoctor Frontend Technology
WeDoctor Frontend Technology
Mastering JavaScript Proxy and Reflect: Deep Dive into Vue 3 Reactivity

Preface

Vue 2’s reactivity system uses Object.defineProperty for data hijacking, which has several drawbacks: it must traverse each property of ordinary objects, cannot detect array changes, cannot monitor Map/Set mutations, and cannot observe addition or deletion of object properties.

Vue 3 adopts Proxy for reactivity, packaged in the @vue/reactivity module. Understanding Proxy is essential for mastering Vue 3’s reactivity.

Proxy Overview

Proxy creates a proxy for an object, allowing interception and customization of fundamental operations such as property lookup, assignment, enumeration, and function invocation.

Basic syntax: const p = new Proxy(target, handler); target is the object to be proxied; it can be any object, including arrays, functions, or another Proxy. Primitive values cannot be used as the target.

handler is an object whose properties are functions (traps) that define custom behavior for operations on the proxy.

Common traps include get, set, and apply. Example:

const obj = { foo: 'bar', fn() { console.log('fn called'); } };
const handler = {
  get(target, key) {
    console.log(`property ${key} was read`);
    return target[key];
  },
  set(target, key, value) {
    console.log(`property ${key} was set to ${value}`);
    target[key] = value;
  },
  apply(target, thisArg, args) {
    console.log('function call intercepted');
    return target.apply(thisArg, args);
  }
};
const p = new Proxy(obj, handler);

p.foo;          // logs: property foo was read
p.foo = 'bar1'; // logs: property foo was set to bar1
p.fn();          // logs: property fn was read, then fn called

Only basic operations are intercepted; compound operations like obj.fn() involve a property read followed by a function call, so only the read is trapped.

Reflect and Proxy

Reflect is a built‑in object that provides methods corresponding to the proxy traps.

For example, Reflect.get(obj, 'foo') performs the default property access.

const obj = { foo: 'foo' };
obj.foo;               // same as
Reflect.get(obj, 'foo');

Using Reflect.get inside a trap preserves the correct this binding:

const handler = {
  get(target, key, receiver) {
    console.log(`property ${key} was read`);
    return Reflect.get(target, key, receiver);
  },
  set(target, key, value, receiver) {
    console.log(`property ${key} was set to ${value}`);
    return Reflect.set(target, key, value, receiver);
  }
};
const obj = { foo: 'foo', get bar() { return this.foo; } };
const p = new Proxy(obj, handler);

p.bar; // triggers both bar and foo reads when bar’s getter accesses this.foo

How Proxy Works Internally

Internal Methods and Slots

ECMAScript specifies object behavior via internal methods and internal slots, identified by double brackets [[...]]. When a property is accessed, the engine invokes the object's [[Get]] internal method.

Objects implement a set of fundamental internal methods; functions also implement [[Call]] and optionally [[Construct]].

Ordinary vs. Exotic Objects

Ordinary objects conform to the standard internal method definitions (e.g., the ten methods in §10.1.x). Exotic objects deviate from these definitions; Proxy is an exotic object because its internal methods are defined in §10.5.x.

Further Proxy Details

When a proxy’s get trap is absent, the operation falls back to the target’s [[Get]]. If the trap exists, it handles the operation on the proxy itself, illustrating the proxy’s transparent nature.

const obj = { foo: 'foo' };
const p = new Proxy(obj, {});

p.foo; // outputs: foo

Conclusion

The article introduced Proxy and its combination with Reflect, explained internal methods and slots from the ECMAScript specification, distinguished ordinary and exotic objects, and clarified how Proxy achieves object interception.

References

Proxy - JavaScript | MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)

Reflect - JavaScript | MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect)

ECMAScript® 2023 Language Specification (https://tc39.es/ecma262/)

Vue.js Design and Implementation (https://www.ituring.com.cn/book/2953)

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ProxyECMAScriptVue3Reactivityreflect
WeDoctor Frontend Technology
Written by

WeDoctor Frontend Technology

Official WeDoctor Group frontend public account, sharing original tech articles, events, job postings, and occasional daily updates from our tech team.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.