<h2>Introdução: Por que Proxy e Reflect Importam para Times Ágeis</h2>
<p>Proxy e Reflect são metaprogramação em JavaScript que permitem interceptar e customizar operações fundamentais em objetos. Para times ágeis que precisam iterar rapidamente, essas APIs são ouro: elas facilitam validação, logging, lazy loading e padrões como Observer sem modificar o código original. A diferença entre um time que consegue refatorar sem medo e outro que não consegue frequentemente está em como lidam com abstrações. Vamos aprender a implementar essas práticas com segurança.</p>
<h2>Fundamentos de Proxy: Interceptando Operações</h2>
<h3>O que é um Proxy?</h3>
<p>Um Proxy é um objeto especial que atua como intermediário entre seu código e o objeto alvo, capturando operações como leitura, escrita e deleção de propriedades. O construtor <code>new Proxy(target, handler)</code> recebe um alvo e um handler (objeto com "armadilhas" ou traps).</p>
<pre><code class="language-javascript">const usuario = {
nome: 'Alice',
email: 'alice@example.com'
};
const usuarioProxy = new Proxy(usuario, {
get(target, prop) {
console.log(Acessando propriedade: ${prop});
return target[prop];
},
set(target, prop, value) {
console.log(Definindo ${prop} = ${value});
if (prop === 'email' && !value.includes('@')) {
throw new Error('Email inválido');
}
target[prop] = value;
return true;
}
});
usuarioProxy.nome; // "Acessando propriedade: nome" → "Alice"
usuarioProxy.email = 'invalido'; // Error: Email inválido</code></pre>
<h3>Casos de Uso Prático</h3>
<p>Validação é apenas o começo. Em times ágeis, Proxies reduzem duplicação ao centralizar regras de negócio. Com lazy loading, você carrega dados sob demanda; com logging transparente, consegue debugging sem poluir classes de negócio. O handler suporta múltiplas traps: <code>get</code>, <code>set</code>, <code>has</code>, <code>deleteProperty</code>, <code>apply</code>, <code>construct</code>, e outras.</p>
<pre><code class="language-javascript">const db = {
usuarios: null // será carregado sob demanda
};
const cache = new Proxy(db, {
get(target, prop) {
if (prop === 'usuarios' && target.usuarios === null) {
console.log('Carregando usuários do banco...');
target.usuarios = [
{ id: 1, nome: 'Alice' },
{ id: 2, nome: 'Bob' }
];
}
return target[prop];
}
});
console.log(cache.usuarios);
// "Carregando usuários do banco..."
// Próximos acessos não recarregam</code></pre>
<h2>Reflect: A API Complementar</h2>
<h3>Entendendo Reflect</h3>
<p>Reflect é um objeto built-in que fornece métodos estáticos para operações interceptáveis. Seu principal benefício é <strong>consistência e segurança</strong>: enquanto <code>obj.prop</code> pode falhar silenciosamente, <code>Reflect.get()</code> retorna valores previsíveis. A combinação Proxy + Reflect é o padrão profissional.</p>
<pre><code class="language-javascript">const pessoa = { nome: 'Carol', idade: 28 };
const handler = {
get(target, prop) {
// Usar Reflect garante o mesmo comportamento do JavaScript
if (prop === 'idade') {
return Reflect.get(target, prop) + 1; // Retorna próxima idade
}
return Reflect.get(target, prop);
},
set(target, prop, value) {
console.log(Mudança rastreada: ${prop});
return Reflect.set(target, prop, value);
}
};
const pessoaProxy = new Proxy(pessoa, handler);
console.log(pessoaProxy.idade); // 29
pessoaProxy.nome = 'David'; // "Mudança rastreada: nome"</code></pre>
<h3>Por Que Não Apenas Usar <code>target[prop]</code>?</h3>
<p>Reflect trata edge cases corretamente: propriedades não-configuráveis, descriptores personalizados e prototype chains. Em times ágeis, isso significa menos bugs em refatorações. Reflect também funciona com símbolos, o que <code>in</code> e <code>delete</code> não fazem uniformemente.</p>
<pre><code class="language-javascript">const simbolo = Symbol('privado');
const obj = {};
Object.defineProperty(obj, simbolo, {
value: 'secreto',
configurable: false
});
const proxy = new Proxy(obj, {
get(target, prop) {
// Reflect respeita propriedades não-configuráveis
return Reflect.get(target, prop);
}
});
console.log(proxy[simbolo]); // "secreto"</code></pre>
<h2>Padrões Avançados para Times Ágeis</h2>
<h3>Validação Reutilizável</h3>
<p>Ao invés de espalhá-la pela codebase, centralize em um factory de validadores:</p>
<pre><code class="language-javascript">function criarProxyValidado(target, esquema) {
return new Proxy(target, {
set(target, prop, value) {
const validador = esquema[prop];
if (validador && !validador(value)) {
throw new TypeError(Validação falhou para ${prop});
}
return Reflect.set(target, prop, value);
}
});
}
const schemaPedido = {
quantidade: (v) => Number.isInteger(v) && v > 0,
preco: (v) => typeof v === 'number' && v >= 0
};
const pedido = criarProxyValidado({}, schemaPedido);
pedido.quantidade = 5; // ✓
pedido.preco = -10; // Error: Validação falhou para preco</code></pre>
<h3>Observable Pattern com Reflect</h3>
<p>Implemente um sistema reativo simples para notificar subscribers de mudanças:</p>
<pre><code class="language-javascript">function criarObservable(target, onChange) {
return new Proxy(target, {
set(target, prop, value) {
const anterior = Reflect.get(target, prop);
const sucesso = Reflect.set(target, prop, value);
if (sucesso && anterior !== value) {
onChange({ prop, anterior, novo: value });
}
return sucesso;
}
});
}
const estado = criarObservable({ contador: 0 }, (mudanca) => {
console.log(${mudanca.prop}: ${mudanca.anterior} → ${mudanca.novo});
});
estado.contador = 1; // "contador: 0 → 1"
estado.contador = 2; // "contador: 1 → 2"</code></pre>
<h2>Conclusão</h2>
<p>Proxy e Reflect são pilares de código escalável e manutenível em JavaScript. Aprendemos que Proxies interceptam operações para validação, logging e lazy loading; Reflect fornece a API correta para acessar essas operações de forma segura e previsível. Em times ágeis, esses padrões reduzem duplicação, centralizam regras e facilitam refatorações sem quebrar a codebase. Comece pequeno—valide um formulário ou implemente um observable—e evolua gradualmente.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy" target="_blank" rel="noopener noreferrer">MDN: Proxy</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect" target="_blank" rel="noopener noreferrer">MDN: Reflect</a></li>
<li><a href="https://javascript.info/proxy" target="_blank" rel="noopener noreferrer">JavaScript.info: Proxy e Reflect</a></li>
<li><a href="https://github.com/getify/You-Dont-Know-JS" target="_blank" rel="noopener noreferrer">You Don't Know JS: Types & Grammar - Kyle Simpson</a></li>
<li><a href="https://tc39.es/ecma262/#sec-proxy-objects" target="_blank" rel="noopener noreferrer">ECMAScript 2015 Specification: Proxy Objects</a></li>
</ul>