Atualizado: 07/12/2024

Proxy - JavaScript

O Proxy representa um objeto que permite interceptar a execução de operações relativas a outro objeto e pode redefinir seu comportamento.

Para criar um objeto Proxy, utiliza-se o construtor Proxy():

const proxy = new Proxy(target, handler);

Este construtor aceita dois parâmetros:

  • target: o objeto alvo do proxy, que pode ser qualquer objeto ao qual o Proxy é aplicado.

  • handler: outro objeto que define quais operações do objeto target serão interceptadas e redefinidas e de que maneira.

// Objeto ao qual o proxy é aplicado
const target = {name: "Tom"};
// Objeto que define como o target será redefinido
const handler = {};
// Objeto proxy
const proxy = new Proxy(target, handler);

console.log(proxy.name);    // Tom

No exemplo acima, target é o objeto ao qual o proxy será aplicado. Neste caso, esse objeto possui a propriedade name:

const target = {name: "Tom"};

Em seguida, cria-se um manipulador handler vazio:

const handler = {};

Esse objeto deve definir como o objeto target será redefinido. No entanto, deixaremos ele vazio por enquanto.

Então, cria-se o objeto Proxy, passando os objetos target e handler para o seu construtor:

const proxy = new Proxy(target, handler);

A função de proxy para o objeto target significa que através do proxy podemos acessar a funcionalidade desse objeto. Neste caso, através do objeto proxy, podemos acessar a propriedade name do objeto target:

console.log(proxy.name); // Tom

Como utilizamos um handler vazio, que não redefine nada, o proxy se comporta exatamente como o objeto original target.

Redefinindo a Funcionalidade de um Objeto com Proxy

Acima, vimos como criar um proxy para um objeto sem, no entanto, redefinir seu comportamento. O aspecto crucial aqui é o manipulador handler, que pode interceptar acessos às propriedades do objeto proxy. Esse manipulador pode definir dois métodos: get e set.

Método get e Acesso às Propriedades do Objeto

O método get intercepta o acesso a uma propriedade ao recuperar seu valor e retorna um valor definido para essa propriedade:

const handler = {
    get: function(target, prop, receiver) {
      return algum_valor;
    }
};

O método get tem três parâmetros:

  • target: o próprio objeto proxyado. Esse parâmetro permite acessar a funcionalidade do objeto original.

  • prop: o nome da propriedade que está sendo acessada.

  • receiver: o objeto Proxy através do qual o proxy está sendo executado.

Considere o seguinte exemplo:

const target = {name: "Tom"};
const handler = {
    get: function(target, prop, receiver) {
    return "Tomas Smith";
    }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name);    // Tomas Smith

Neste caso, o manipulador handler no método get retorna a string "Tomas Smith":

get: function(target, prop, receiver) {
    return "Tomas Smith";
}

Isso faz com que, ao acessar qualquer propriedade do objeto proxy, seja retornada a string mencionada:

console.log(proxy.name); // Tomas Smith

Esse exemplo demonstra como interceptar o acesso a uma propriedade e redefinir a resposta de forma simples. No entanto, ainda podemos acessar o objeto original que está sendo proxyado:

const target = {name: "Tom"};
const handler = {
    get: function(target, prop) {
    return "Name: " + target.name;
    }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name);    // Name: Tom

Aqui, o manipulador retorna a string "Name: " + target.name, onde target.name é o acesso à propriedade name do objeto original. A lógica para retornar o valor de uma propriedade pode ser mais complexa.

Considere um objeto mais complexo com duas propriedades:

const target = {name: "Tom", age: 37};
const handler = {
    get: function(target, prop) {
    return target[prop];
    }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name);    // Tom
console.log(proxy.age);     // 37

Neste caso, o objeto alvo possui duas propriedades: name e age. O manipulador intercepta o acesso a essas propriedades, mas não redefine, apenas retorna os valores das propriedades originais:

return target[prop];

Acesso às propriedades do objeto alvo é feito usando a sintaxe de arrays.

No entanto, podemos verificar qual propriedade está sendo acessada e realizar alguma redefinição:

const target = {name: "Tom", age: 37};
const handler = {
    get: function(target, prop) {
    if (prop === "name")
        return target.name.toUpperCase();
    else
        return target[prop];
    }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name);    // TOM
console.log(proxy.age);     // 37

Neste exemplo, se o acesso é à propriedade name, ou seja, à propriedade que armazena uma string, chamamos o método toUpperCase() nessa string para convertê-la em maiúsculas.

Configurando Propriedades e o Método set

O método set intercepta as operações de atribuição de valores a propriedades:

const handler = {
    set: function(target, property, value, receiver) {
        
    }
};

O método set possui quatro parâmetros:

  • target: o objeto original que está sendo proxyado.

  • property: o nome da propriedade que está sendo acessada.

  • value: o valor que está sendo atribuído.

  • receiver: o objeto Proxy através do qual a operação está sendo realizada.

Vamos analisar um exemplo:

const target = {name: "Tom", age: 37};
const handler = {
    set: function(target, prop, value) {
        console.log(value);
        target[prop] = value;
    }
};
const proxy = new Proxy(target, handler);
proxy.name = "Tomas";
console.log(proxy.name);    // Tomas
proxy.age = 22;             
console.log(proxy.age);     // 22

Neste exemplo, o método set primeiro registra o valor que está sendo atribuído à propriedade e, em seguida, configura essa propriedade:

target[prop] = value;

Agora, vamos modificar o exemplo para incluir uma validação:

const target = {name: "Tom", age: 37};
const handler = {
    set: function(target, prop, value) {
    if(prop === "age" && value < 1)
        console.log("Idade incorreta");
    else
        return target[prop] = value;
    }
};
const proxy = new Proxy(target, handler);
proxy.name = "Tomas";
console.log(proxy.name);    // Tomas
proxy.age = -199;           // Idade incorreta
console.log(proxy.age);     // 37
proxy.age = 22;             
console.log(proxy.age);     // 22

Neste caso, dentro do método set, verificamos se a propriedade sendo configurada é age e se o valor é menor que 1. Se estas condições forem verdadeiras, simplesmente imprimimos uma mensagem indicando que a idade é incorreta:

if(prop === "age" && value < 1)
    console.log("Idade incorreta");

Caso contrário, atribuímos o valor à propriedade do objeto original:

else
    return target[prop] = value;
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com