Skip to main content

JavaScript Performance

JavaScript Reflect

Written by Published

Reflect provides the same operations as a Proxy trap, as plain functions you can call directly.

It mirrors the traps a Proxy handler can define.

Its main job is forwarding an operation from inside a trap to the real target.

Example

Example

javascript

const person = { name: "Ada" };

console.log(Reflect.get(person, "name"));
console.log(Reflect.has(person, "name"));

Both do exactly what the equivalent plain syntax would do.

Reflect's Methods

Reflect.get and Reflect.set read and write a property.

Reflect.has is the same check as the in operator.

Reflect.ownKeys lists an object's own property names.

Syntax

Syntax

javascript

Reflect.get(target, key);
Reflect.set(target, key, value);

Every Reflect method has a matching Proxy trap of the same name.

Forwarding Inside a Proxy

This is the pattern you will see constantly.

The trap does something extra, then forwards the real work to Reflect.

Example

Example

javascript

const target = { name: "Ada" };
const reads = [];

const proxy = new Proxy(target, {
  get(obj, key) {
    reads.push(key);
    return Reflect.get(obj, key);
  }
});

console.log(proxy.name);
console.log(reads.join(","));

Reflect.get does exactly what obj[key] would, but as a function call.

Reflect.set Returns Success or Failure

Unlike a plain assignment, it tells you whether the write actually worked.

Example

Example

javascript

const frozen = Object.freeze({ name: "Ada" });

const succeeded = Reflect.set(frozen, "name", "Grace");

console.log(succeeded);
console.log(frozen.name);

The output is false then Ada: the frozen object refused the write.

Listing Own Keys

This includes both string and symbol keys, unlike Object.keys.

Example

Example

javascript

const person = { name: "Ada", age: 36 };

console.log(Reflect.ownKeys(person).join(","));

The output is name,age.

Deleting Through Reflect

Reflect.deleteProperty mirrors the delete operator, and returns success.

Example

Example

javascript

const person = { name: "Ada", age: 36 };

const removed = Reflect.deleteProperty(person, "age");

console.log(removed);
console.log(Reflect.has(person, "age"));

The output is true then false.

Why Not Just Use Plain Syntax?

For everyday code, obj.prop and obj.prop = value are perfectly fine.

Reflect exists for exactly one job: mirroring Proxy traps as callable functions.

Example

Example

javascript

const target = { name: "Ada" };

const plain = target.name;
const viaReflect = Reflect.get(target, "name");

console.log(plain === viaReflect);

Both give the same answer; Reflect is only needed inside a trap.

Complete Example

Complete Example

html

<!DOCTYPE html>
<html>
<head>
  <title>JavaScript Reflect</title>
</head>
<body>

  <h1>Reflect</h1>

  <p id="out"></p>

  <script>
    const target = { name: "Ada", age: 36 };
    const log = [];

    const proxy = new Proxy(target, {
      get(obj, key) {
        log.push("read " + String(key));
        return Reflect.get(obj, key);
      },
      set(obj, key, value) {
        log.push("wrote " + String(key));
        return Reflect.set(obj, key, value);
      }
    });

    proxy.name;
    proxy.age = 37;

    document.getElementById("out").innerHTML =
      log.join("<br>") + "<br>New age: " + target.age;
  </script>

</body>
</html>

Try It Yourself

Run the above example in the Try It Editor.

Try Reflect.has:

Add console.log(Reflect.has(target, "age")) and check the result.

Important Points

  • Reflect provides the same operations as Proxy traps, as functions.
  • Reflect.get and set read and write properties.
  • Reflect.set returns whether the write actually succeeded.
  • Reflect.ownKeys lists every own property key.
  • Its main use is forwarding an operation from inside a Proxy trap.

Conclusion

Reflect and Proxy are designed as a pair.

Outside a Proxy trap you will rarely need it; plain syntax is simpler.

Together they are the mechanism behind reactive libraries and validation wrappers alike.