Search code examples
javascriptreflectionecmascript-6es6-proxy

What is the difference between Proxy constructor and Reflect?


Is there any significant difference between Reflect and Proxy?

From what is documented, it seems that they have pretty much the same capabilities, apart from:

  • Reflect being capable of specifying only one trap at the time.
  • Proxy being revocable.
  • Proxy being a constructor.

If the list above sums up all the differences, then what is the rationale for having both?


Solution

  • Reflect and Proxy have completely different purposes and different capabilities.

    MDN describes Proxy in this way:

    The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

    And Reflect in this way:

    Reflect is a built-in object that provides methods for interceptable JavaScript operations. The methods are the same as those of proxy handlers.

    I realize that you've probably already read that, so I'll use an example to explain it further.

    Let's say you have an object:

    const obj = {
      a: 'foo',
      b: 'bar',
    };
    

    You can access property a using a property accessor like this:

    console.log(obj.a); // 'foo'
    

    You can do the same using Reflect.get() method:

    console.log(Reflect.get(obj, 'a')); // 'foo'
    

    You can also create a proxy of that object using the Proxy constructor. We'll use the get handler for intercepting all property lookups.

    const proxy = new Proxy(obj, {
      get(target, property) {
        return property in target ? target[property] : 'default';
      },
    });
    

    Now using either property accessor or Reflect.get() to get an undefined property results in string 'default':

    console.log(proxy.c); // 'default'
    console.log(Reflect.get(proxy, 'c')); // 'default'
    

    Proxy and Reflect can work great together. You can for example create a Proxy with a no-op get handler using Reflect:

    new Proxy(obj, {
      get: Reflect.get,
    });