patrocínio:

Decifrando Proxies em JavaScript

Intercepte seus objetos utilizando Proxies.

por Helder Burato Berto 06/07/2018 Comentários ~ 3 min. / 490 palavras

Neste post vamos abordar o objeto Proxy incluído na versão ECMAScript 6, criando a possibilidade de interceptação de operações e viabilizando a criação de métodos customizados.

Desvendando o objeto Proxy

O objeto Proxy é utilizado para criar comportamentos customizados, tem como padrão alguns parâmetros que podemos ver a seguir:

  • target: Objeto que está sendo virtualizado pelo Proxy;
  • handler: Objeto que contém as armadilhas (traps);
  • traps: São métodos utilizados para interceptar operações nas propriedades de um objeto.

Criando nosso primeiro Proxy

Nesta primeira etapa, criaremos um Proxy simples com o objetivo de utilizarmos o objeto handler, onde incluiremos uma armadilha (trap) para que uma das propriedades do objeto tenha um valor padrão caso a propriedade não seja definida. Vamos lá?

const handler = {
  get: function(obj, prop) {
    return prop in obj ? obj[prop] : 1;
  }
};

const target = {};
const proxy = new Proxy(target, handler);
proxy.age = 20;

console.log(proxy.age, proxy.active); // => 20 1
> 20 1

Elaborando uma validação

Vamos utilizar o exemplo anterior e criar uma nova armadilha no objeto handler, aplicando o método set. Confira a seguir:

const handler = {
  get: function(obj, prop) {
    return prop in obj ? obj[prop] : 1;
  },
  set: function(target, prop, value, receiver) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError(`The property age isn't a number.`);
      }
    }

    // For default the value will be add to the property in the object
    target[prop] = value;

    // Indicate the success
    return true;
  }
};

const target = {};
const proxyOne = new Proxy(target, handler);
proxyOne.age = 20;

console.log(proxyOne.age, proxyOne.active); // => 20 1
> 20 1

const proxyTwo = new Proxy(target, handler);
proxyTwo.age = 'Hello World';

console.log(proxyTwo.age); // => "TypeError: The property age isn't a number."
> "TypeError: The property age isnt a number."

Cancelando armadilhas (traps)

Vamos utilizar o método Proxy.revocable() para cancelar as armadilhas de um proxy. Confira a seguir:

const handler = {
  get: function(obj, prop) {
    return prop in obj ? obj[prop] : 1;
  },
  set: function(target, prop, value, receiver) {
    // For default the value will be add to the property in the object
    target[prop] = value;

    // Indicate the success
    return true;
  }
};

const target = {
  firstName: "Helder",
  lastName: "Burato Berto"
};

const { proxy, revoke } = Proxy.revocable(target, handler);

console.log(`${proxy.firstName} ${proxy.lastName}`); // => "Helder Burato Berto"
> "Helder Burato Berto"

revoke(); // Revoke access to the proxy

console.log(`${proxy.firstName} ${proxy.lastName}`); // => "TypeError: Cannot perform 'get' on a proxy that has been revoked"
> "TypeError: Cannot perform 'get' on a proxy that has been revoked"

Depois que você fizer a chamada revoke() todas as operações relacionadas ao objeto Proxy vão causar um TypeError, desta forma você consegue prevenir que ocorram ações em objetos indevidos.

Conclusão

Com os exemplos acima, podemos ilustrar como o objeto Proxy pode nos ajudar em nosso dia a dia. Outros exemplos de uso e métodos de armadilhas (traps) você pode encontrar em: