W3docs

JavaScript Proxy e Reflect

Aprenda como JavaScript Proxy e Reflect funcionam: intercepte operações get, set, apply, has e delete com traps e aplique proxies para validação, controle de acesso e logging.

Os proxies de JavaScript permitem interceptar e redefinir as operações fundamentais sobre objects — leitura de uma propriedade, escrita, verificação de existência de uma chave, chamada de função e muito mais. Combinados com a API Reflect, que executa essas mesmas operações da forma "padrão", os proxies oferecem um mecanismo limpo e oficial para adicionar comportamento a objects sem modificá-los diretamente.

Este capítulo aborda o que é um proxy, as traps mais comuns (get, set, apply, has, deleteProperty), como o Reflect complementa os proxies e alguns padrões do mundo real, como validação, controle de acesso e logging.

O que é um Proxy

Um Proxy envolve um objeto alvo e um handler. O handler é um conjunto de funções chamadas traps, cada uma interceptando uma operação específica. Quando você interage com o proxy, a trap correspondente é executada em vez do comportamento padrão; se nenhuma trap for definida para uma operação, o proxy a encaminha ao alvo sem alterações.

Isso é útil sempre que você deseja adicionar comportamento transversal — logging, validação, valores padrão, regras de acesso — a um object sem alterar seu próprio código.

Sintaxe do Proxy

const proxy = new Proxy(target, handler);
  • target: O object original cujas operações você deseja interceptar.
  • handler: Um object cujos métodos (traps) definem como as operações se comportam.

Você então usa proxy exatamente como usaria o object original; a diferença é que suas traps são executadas no meio.

Entendendo a Trap get

A trap get intercepta leituras de propriedades no object alvo. Ela recebe o target, a chave property e o receiver (o próprio proxy). É frequentemente usada para registrar acessos, calcular propriedades dinamicamente ou retornar valores padrão para chaves ausentes.

Exemplo:

javascript— editable

Este código configura um proxy para registrar acessos a propriedades de um object.

  • Handler: Define uma trap get para registrar a propriedade acessada.
  • Object Alvo: Contém as propriedades name e age.
  • Proxy: Envolve o object target com o handler.

Quando proxy.name é acessado, registra "Getting name" e retorna "John". Isso é útil para monitorar ou depurar acessos a propriedades.

Manipulando Operações de Object com as Traps set e apply

A Trap set

A trap set pode impor regras para atribuições de propriedades, garantindo que as propriedades contenham tipos específicos ou atendam a certas condições.

Exemplo:

javascript— editable

Este código configura um proxy para validar e registrar atribuições de propriedades em um object.

  • Handler: Define uma trap set para verificar se a propriedade age possui valores válidos e registrar tentativas de defini-la.
  • Proxy: Envolve o object target com o handler.

Quando proxy.age é definido, verifica se é uma idade válida (0-150). Se inválida, registra um erro e lança uma exceção.

A Trap apply

O método apply em um JavaScript Proxy intercepta chamadas de função. Ele recebe três argumentos:

  1. target: A função original sendo chamada.
  2. thisArg: O valor de this dentro da função.
  3. argumentsList: Um array de argumentos passados para a função.

Exemplo:

javascript— editable

Este código configura um proxy para registrar chamadas de função e seus argumentos.

  • Handler: Define uma trap apply para registrar os argumentos quando a função é chamada.
  • Função: sum soma dois números.
  • Proxy: Envolve a função sum com o handler.

No código fornecido, a trap apply registra os argumentos e então chama a função original usando target.apply(thisArg, argumentsList). Isso é útil para logging, depuração ou modificação dinâmica do comportamento de funções.

A Trap has

A trap has intercepta o operador in. Um uso comum é ocultar chaves "privadas" (por convenção, nomes que começam com _) para que não pareçam existir externamente.

Exemplo:

javascript— editable

Mesmo que _secret ainda exista no alvo, o operador in retorna false, de modo que a chave fica efetivamente oculta para código que inspeciona o object.

A Trap deleteProperty

A trap deleteProperty intercepta o operador delete, permitindo proteger certas chaves de remoção. Ela deve retornar true quando a exclusão é permitida, ou lançar um erro para bloqueá-la no modo estrito.

Exemplo:

javascript— editable
Aviso

Os proxies de JavaScript são poderosos, mas devem ser usados com sabedoria. O uso excessivo de proxies pode tornar o código mais difícil de entender e manter. Observe que proxies introduzem uma pequena sobrecarga de desempenho em comparação com objects nativos.

API Reflect

Reflect é um object nativo que fornece um método para cada operação interceptável — exatamente o mesmo conjunto coberto pelas traps de proxy (Reflect.get, Reflect.set, Reflect.has, Reflect.deleteProperty, Reflect.apply, entre outros). Cada método executa a versão padrão dessa operação.

Isso faz do Reflect o complemento natural do Proxy: dentro de uma trap, normalmente você quer adicionar algum comportamento e depois deixar a operação prosseguir normalmente. Chamar o método Reflect correspondente faz exatamente isso, e ele encaminha o receiver corretamente (importante para getters/setters), o que um simples target[property] não faz. Você verá esse padrão nos exemplos práticos abaixo.

Os métodos do Reflect também retornam valores em vez de lançar exceções — por exemplo, Reflect.set retorna um boolean indicando sucesso — o que torna as operações mais previsíveis do que seus equivalentes com operadores ou Object.*.

Aqui está um tour rápido pelos principais métodos do Reflect:

1. Reflect.get()

Este método é usado para obter o valor de uma propriedade de um object.

Exemplo:

javascript— editable

2. Reflect.set()

Este método é usado para definir o valor de uma propriedade em um object.

Exemplo:

javascript— editable

3. Reflect.has()

Este método verifica se uma propriedade existe em um object.

Exemplo:

javascript— editable

4. Reflect.deleteProperty()

Este método exclui uma propriedade de um object.

Exemplo:

javascript— editable

5. Reflect.ownKeys()

Este método retorna todas as chaves de propriedades próprias de um object.

Exemplo:

javascript— editable

6. Reflect.apply()

Este método chama uma função alvo com os argumentos fornecidos.

Exemplo:

javascript— editable

7. Reflect.construct()

Este método é usado para criar uma nova instância de um object.

Exemplo:

javascript— editable

Esses exemplos mostram como você pode usar os métodos Reflect para realizar operações comuns em objects de forma mais limpa e consistente.

Casos de Uso Práticos de Proxies em JavaScript

Exemplo 1: Inicialização Automática de Propriedades

Descrição: Use proxies de JavaScript para inicializar automaticamente propriedades undefined em um object. Isso pode ser útil em situações em que objects são preenchidos dinamicamente com dados ao longo do tempo, como configurações de usuário ou configurações que podem não estar definidas inicialmente.

javascript— editable

Este código cria um proxy que verifica se uma propriedade existe em um object. Se não existir, o proxy define automaticamente um valor padrão para ela. Isso é útil para evitar erros causados por propriedades ausentes.

Exemplo 2: Controle de Acesso

Descrição: Proxies podem impor permissões de leitura ou escrita em propriedades de objects. Este exemplo demonstra um proxy que impede que certas propriedades sejam lidas ou escritas com base em regras predefinidas, o que é particularmente útil para gerenciar o acesso a dados sensíveis.

javascript— editable

Este código protege um object controlando o acesso às suas propriedades. Ele bloqueia a leitura de 'sensitiveData' e impede a alteração de propriedades 'readOnly', ajudando a manter os dados seguros.

Exemplo 3: Logging e Depuração

Descrição: Proxies podem ser usados para registrar interações com um object, o que ajuda na depuração e no monitoramento de operações. Este exemplo cria um proxy que registra todos os gets, sets e chamadas de método realizados em um object.

javascript— editable

Este código rastreia cada vez que alguém acessa ou altera uma propriedade do object, o que é ótimo para entender o que seu código está fazendo e quando.

Exemplo 4: Validação de Dados

Descrição: Use proxies para validação em tempo real de propriedades de objects. Isso é particularmente útil para garantir a integridade dos dados quando objects são atualizados dinamicamente em uma aplicação.

javascript— editable

Este exemplo demonstra como usar o Proxy do JavaScript para validar e registrar alterações de propriedades. O object validator verifica se a propriedade age é um número válido entre 0 e 150. Se não for, registra um erro e lança uma exceção. Caso contrário, registra o novo valor e atualiza a propriedade. O object person usa esse validador para gerenciar sua propriedade age, garantindo que idades inválidas sejam capturadas e registradas.

Conclusão

Dominar os proxies de JavaScript permite controlar e estender o comportamento de objects sem modificá-los diretamente. Os proxies podem impor regras de validação e acesso, fornecer valores padrão e alimentar ferramentas de logging ou depuração, enquanto o Reflect mantém as operações subjacentes limpas e previsíveis. Usados com moderação, ajudam a construir aplicações mais dinâmicas e seguras.

Para se aprofundar nas operações que os proxies interceptam, consulte getters e setters de propriedades e flags e descritores de propriedades. Para o padrão de validação mostrado acima, tratamento de erros com try...catch e classes são companheiros úteis.

Prática

Prática
Qual é a principal funcionalidade dos objects Proxy e Reflect do JavaScript?
Qual é a principal funcionalidade dos objects Proxy e Reflect do JavaScript?
Was this page helpful?