[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Meta_programming#revocable_proxy [Back]  [Original]

Meta programao - JavaScript | MDN

Esta pgina foi traduzida do ingls pela comunidade. Saiba mais e junte-se comunidade MDN Web Docs.

View in English Always switch to English

Meta programao

Comeando com ECMAScript 6, o JavaScript ganha suporte para os objetos Proxy e Reflect, permitindo voc interceptar e definir o comportamento personalizado para operaes fundamentais da linguagem (por exemplo, pesquisa de propriedade, atribuio, enumerao, invocao de funo, etc). Com a ajuda destes dois objetos voc ser capaz de programar a nvel meta em JavaScript.

In this article

Proxies

Introduzido em ECMAScript 6, objetos Proxy permitem que voc intercepte determinadas operaes e implementar comportamentos personalizados. Por exemplo, receber uma propriedade em um objeto:

js
var handler = {
  get: function (target, name) {
    return name in target ? target[name] : 42;
  },
};
var p = new Proxy({}, handler);
p.a = 1;
console.log(p.a, p.b); // 1, 42

O objeto Proxy define um target (um objeto vazio aqui) e um objeto handler em que um get trap implementado. Aqui, um objeto que est em proxy no retornar indefinido quando receber propriedades indefinidas, mas, ao contrrio, retornar o nmero 42.

Exemplos adicionais esto disponveis na pgina de referncia de Proxy .

Terminologia

Os seguintes termos so usados quando se fala sobre a funcionalidade de proxies.

handler

Espao reservado de objeto que contenha traps.

traps

Os mtodos que fornecem acesso de propriedade. Isto anlogo ao conceito de traps em sistemas operacionais.

target

Objeto que o proxy est virtualizando. Ele frequentemente usado como backend de armazenamento para o proxy. Invariantes (semnticas que permanecem inalteradas) relativas a objetos que no podem ser extendidos ou propriedades que no podem ser configuradas so comparadas com o target.

invariantes

Semnticas que permanecem inalteradas na execuo de operaes personalizadas so chamados de invariantes. Se voc violar as invariantes de um manipulador, um TypeError ser lanado.

Handlers e traps

A tabela a seguir resume as traps disponveis aos objetos do tipo Proxy. Veja as pginas de referncia para explicaes detalhadas e exemplos.

Handler / trap Interceptions Invariants
handler.getPrototypeOf() Object.getPrototypeOf()
Reflect.getPrototypeOf()
__proto__
Object.prototype.isPrototypeOf()
instanceof
  • O mtodo getPrototypeOf deve retornar um object ou null.
  • Se target no puder ser extendido, o mtodo Object.getPrototypeOf(proxy) deve retornar o mesmo valor que Object.getPrototypeOf(target).
handler.setPrototypeOf() Object.setPrototypeOf()
Reflect.setPrototypeOf()

Se target no puder ser extendido, o parmetro prototype dever ter o mesmo valor que Object.getPrototypeOf(target).

handler.isExtensible() Object.isExtensible()
Reflect.isExtensible()
Object.isExtensible(proxy) deve retornar o mesmo valor que Object.isExtensible(target).
handler.preventExtensions() Object.preventExtensions()
Reflect.preventExtensions()
Object.preventExtensions(proxy) retorna true somente se Object.isExtensible(proxy) retornar false.
handler.getOwnPropertyDescriptor() Object.getOwnPropertyDescriptor()
Reflect.getOwnPropertyDescriptor()
  • getOwnPropertyDescriptor deve retornar um object ou undefined.
  • Uma propriedade no pode ser descrita como no existente se ela existir como uma propriedade prpria e no configurvel do objeto alvo.
  • Uma propriedade no pode ser relatada como inexistente, se existir como uma propriedade prpria do objeto de destino e o objeto de destino no for extensvel.
  • Uma propriedade no pode ser relatada como existente, se no existir como uma propriedade prpria do objeto de destino e o objeto de destino no for extensvel.
  • Uma propriedade no pode ser relatada como no configurvel, se no existir como uma propriedade prpria do objeto de destino ou se existir como uma propriedade prpria configurvel do objeto de destino.
  • O resultado de Object.getOwnPropertyDescriptor(target) pode ser aplicado ao objeto de destino usando Object.defineProperty e no emitir uma exceo.
handler.defineProperty() Object.defineProperty()
Reflect.defineProperty()
  • Uma propriedade no pode ser adicionada se o objeto de destino no for extensvel.
  • Uma propriedade no pode ser adicionada como ou modificada para no ser configurvel, se no existir como uma propriedade prpria no configurvel do objeto de destino.
  • Uma propriedade pode no ser no configurvel, se existir uma propriedade configurvel correspondente do objeto de destino.
  • Se uma propriedade tiver uma propriedade de objeto de destino correspondente Object.defineProperty(target, prop, descriptor) no lanar uma exceo.
  • No modo estrito, um valor de retorno false do manipulador defineProperty manipulador lanar um TypeError exceo.
handler.has() Property query: foo in proxy
Inherited property query: foo in Object.create(proxy)
Reflect.has()
  • Uma propriedade no pode ser relatada como inexistente, se existir como uma propriedade prpria no configurvel do objeto de destino.
  • Uma propriedade no pode ser relatada como inexistente, se existir como uma propriedade prpria do objeto de destino e o objeto de destino no for extensvel.
handler.get() 1 Property access: proxy[foo]and proxy.bar
Inherited property access: Object.create(proxy)[foo]
Reflect.get()
  • O valor relatado para uma propriedade deve ser igual ao valor da propriedade do objeto de destino correspondente se a propriedade do objeto de destino for uma propriedade de dados no gravvel e no configurvel.
  • O valor relatado para uma propriedade deve ser indefinido se a propriedade do objeto de destino correspondente for uma propriedade acessora no configurvel que tenha sido indefinida como seu atributo [[Get]].
handler.set() Property assignment: proxy[foo] = bar and proxy.foo = bar
Inherited property assignment: Object.create(proxy)[foo] = bar
Reflect.set()
  • No possvel alterar o valor de uma propriedade para ser diferente do valor da propriedade do objeto de destino correspondente se a propriedade do objeto de destino correspondente for uma propriedade de dados no gravvel e no configurvel.
  • No possvel definir o valor de uma propriedade se a propriedade do objeto de destino correspondente for uma propriedade acessadora no configurvel que tenha undefined como seu atributo [[Set]].
  • No modo estrito, um valor de retorno false do manipulador set lanar uma exceo TypeError.
handler.deleteProperty() Property deletion: delete proxy[foo] and delete proxy.foo
Reflect.deleteProperty()
Uma propriedade no pode ser excluda, se existir como uma propriedade prpria no configurvel do objeto de destino.
handler.enumerate() Property enumeration / for...in: for (var name in proxy) {...}
Reflect.enumerate()

O mtodo enumerate deve retornar um objeto.

handler.ownKeys() Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
  • O resultado de ownKeys uma lista.
  • O tipo de cada elemento da lista de resultados String ou Symbol.
  • A lista de resultados deve conter as chaves de todas as propriedades prprias no configurveis do objeto de destino.
  • Se o objeto de destino no for extensvel, a Lista de resultados dever conter todas as chaves das prprias propriedades do objeto de destino e nenhum outro valor.
handler.apply() proxy(..args)
Function.prototype.apply() and Function.prototype.call()
Reflect.apply()

No h invariantes para o mtodo handler.apply

handler.construct() new proxy(...args)
Reflect.construct()
O resultado deve ser um Object.

Proxy Revogvel

O mtodo Proxy.revocable() utilizado para criar um objeto Proxy revogvel. Isso significa que o proxy pode ser revogado atravs da funo revoke, desligando-o. Depois disso, qualquer operao com o proxy lanar um TypeError.

js
var revocable = Proxy.revocable(
  {},
  {
    get: function (target, name) {
      return "[[" + name + "]]";
    },
  },
);
var proxy = revocable.proxy;
console.log(proxy.foo); // "[[foo]]"

revocable.revoke();

console.log(proxy.foo); // TypeError  lanado
proxy.foo = 1; // TypeError novamente
delete proxy.foo; // ainda um TypeError
typeof proxy; // "object", typeof no desencadeia nenhuma trap

Reflexo

Reflect um objeto embutido que contm mtodos que permitem a criao de operaes interceptveis em JavaScript. Os mtodos so iguais queles de proxy handlers. Reflect no um objeto do tipo function.

Reflect auxilia no encaminhamento de operaes padro do handler para o target.

Reflect.has(), por exemplo, tem o mesmo efeito prtico que o operador in, com a facilidade de ser utilizado como uma funo:

js
Reflect.has(Object, "assign"); // true

Uma funo apply melhorada

Em ES5, voc normalmente utiliza o mtodo Function.prototype.apply() para invocar uma funo com um dado valor para this e arguments fornecido como um array (ou um objeto parecido com um array).

js
Function.prototype.apply.call(Math.floor, undefined, [1.75]);

Com Reflect.apply essa operao se torna menos verbosa e mais fcil de compreender:

js
Reflect.apply(Math.floor, undefined, [1.75]);
// 1;

Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]);
// "hello"

Reflect.apply(RegExp.prototype.exec, /ab/, ["confabulation"]).index;
// 4

Reflect.apply("".charAt, "ponies", [3]);
// "i"

Verificando se a definio da propriedade obteve sucesso

Com Object.defineProperty, a qual retorna um object em caso de sucesso ou lana um TypeError em caso contrrio, voc utilizaria um bloco try...catch para capturar qualquer erro que tenha ocorrido ao definir uma propriedade. Devido ao fato de Reflect.defineProperty retornar um status do tipo Boolean, voc pode simplesmente utilizar aqui um bloco if...else:

js
if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}

Web Proxy Viewer  |  New URL  |  Original Page