Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Esta página foi traduzida do inglês pela comunidade. Saiba mais e junte-se à comunidade MDN Web Docs.

Meta programação

Começando com ECMAScript 6, o JavaScript ganha suporte para os objetosProxy eReflect, permitindo você interceptar e definir o comportamento personalizado para operações fundamentais da linguagem (por exemplo, pesquisa de propriedade, atribuição, enumeração, invocação de função, etc). Com a ajuda destes dois objetos você será capaz de programar a nívelmeta em JavaScript.

Proxies

Introduzido em ECMAScript 6, objetosProxy permitem que você intercepte determinadas operações 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 umtarget (um objeto vazio aqui) e um objetohandler em que umgettrap é implementado. Aqui, um objeto que está em proxy não retornará indefinido quando receber propriedades indefinidas, mas, ao contrário, retornar o número 42.

Exemplos adicionais estão disponíveis na página de referência deProxy .

Terminologia

Os seguintes termos são usados quando se fala sobre a funcionalidade de proxies.

handler

Espaço reservado de objeto que contenha traps.

traps

Os métodos que fornecem acesso de propriedade. Isto é análogo 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 (semânticas que permanecem inalteradas) relativas a objetos que não podem ser extendidos ou propriedades que não podem ser configuradas são comparadas com o target.

invariantes

Semânticas que permanecem inalteradas na execução de operações personalizadas são chamados deinvariantes. Se você violar as invariantes de um manipulador, umTypeError será lançado.

Handlers e traps

A tabela a seguir resume as traps disponíveis aos objetos do tipo Proxy. Veja aspáginas de referência para explicações detalhadas e exemplos.

Handler / trapInterceptionsInvariants
handler.getPrototypeOf()Object.getPrototypeOf()
Reflect.getPrototypeOf()
__proto__
Object.prototype.isPrototypeOf()
instanceof
  • O métodogetPrototypeOf deve retornar um object ounull.
  • Setarget não puder ser extendido, o métodoObject.getPrototypeOf(proxy) deve retornar o mesmo valor queObject.getPrototypeOf(target).
handler.setPrototypeOf()Object.setPrototypeOf()
Reflect.setPrototypeOf()

Setargetnão puder ser extendido, o parâmetroprototypedever ter o mesmo valor queObject.getPrototypeOf(target).

handler.isExtensible()Object.isExtensible()
Reflect.isExtensible()
Object.isExtensible(proxy) deve retornar o mesmo valor queObject.isExtensible(target).
handler.preventExtensions()Object.preventExtensions()
Reflect.preventExtensions()
Object.preventExtensions(proxy) retornatrue somente seObject.isExtensible(proxy) retornarfalse.
handler.getOwnPropertyDescriptor()Object.getOwnPropertyDescriptor()
Reflect.getOwnPropertyDescriptor()
  • getOwnPropertyDescriptor deve retornar um object ouundefined.
  • Uma propriedade não pode ser descrita como não existente se ela existir como uma propriedade própria e não configurável do objeto alvo.
  • Uma propriedade não pode ser relatada como inexistente, se existir como uma propriedade própria do objeto de destino e o objeto de destino não for extensível.
  • Uma propriedade não pode ser relatada como existente, se não existir como uma propriedade própria do objeto de destino e o objeto de destino não for extensível.
  • Uma propriedade não pode ser relatada como não configurável, se não existir como uma propriedade própria do objeto de destino ou se existir como uma propriedade própria configurável do objeto de destino.
  • O resultado deObject.getOwnPropertyDescriptor(target) pode ser aplicado ao objeto de destino usandoObject.defineProperty e não emitirá uma exceção.
handler.defineProperty()Object.defineProperty()
Reflect.defineProperty()
  • Uma propriedade não pode ser adicionada se o objeto de destino não for extensível.
  • Uma propriedade não pode ser adicionada como ou modificada para não ser configurável, se não existir como uma propriedade própria não configurável do objeto de destino.
  • Uma propriedade pode não ser não configurável, se existir uma propriedade configurável correspondente do objeto de destino.
  • Se uma propriedade tiver uma propriedade de objeto de destino correspondenteObject.defineProperty(target, prop, descriptor) não lançará uma exceção.
  • No modo estrito, um valor de retornofalse do manipuladordefineProperty manipulador lançará umTypeError exceção.
handler.has() Property query:foo in proxy
Inherited property query:foo in Object.create(proxy)
Reflect.has()
  • Uma propriedade não pode ser relatada como inexistente, se existir como uma propriedade própria não configurável do objeto de destino.
  • Uma propriedade não pode ser relatada como inexistente, se existir como uma propriedade própria do objeto de destino e o objeto de destino não for extensível.
handler.get() 1 Property access:proxy[foo]andproxy.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 não gravável e não configurável.
  • O valor relatado para uma propriedade deve ser indefinido se a propriedade do objeto de destino correspondente for uma propriedade acessora não configurável que tenha sido indefinida como seu atributo [[Get]].
handler.set() Property assignment:proxy[foo] = bar andproxy.foo = bar
Inherited property assignment:Object.create(proxy)[foo] = bar
Reflect.set()
  • Não é possível 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 não gravável e não configurável.
  • Não é possível definir o valor de uma propriedade se a propriedade do objeto de destino correspondente for uma propriedade acessadora não configurável que tenhaundefined como seu atributo [[Set]].
  • No modo estrito, um valor de retornofalse do manipuladorset lançará uma exceçãoTypeError.
handler.deleteProperty() Property deletion:delete proxy[foo] anddelete proxy.foo
Reflect.deleteProperty()
Uma propriedade não pode ser excluída, se existir como uma propriedade própria não configurável do objeto de destino.
handler.enumerate() Property enumeration / for...in:for (var name in proxy) {...}
Reflect.enumerate()

O métodoenumerate deve retornar um objeto.

handler.ownKeys()Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
  • O resultado deownKeys é uma lista.
  • O tipo de cada elemento da lista de resultados éString ouSymbol.
  • A lista de resultados deve conter as chaves de todas as propriedades próprias não configuráveis do objeto de destino.
  • Se o objeto de destino não for extensível, a Lista de resultados deverá conter todas as chaves das próprias propriedades do objeto de destino e nenhum outro valor.
handler.apply()proxy(..args)
Function.prototype.apply() andFunction.prototype.call()
Reflect.apply()

Não há invariantes para o métodohandler.apply

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

Proxy Revogável

O métodoProxy.revocable() é utilizado para criar um objeto Proxy revogável. Isso significa que o proxy pode ser revogado através da funçãorevoke, desligando-o. Depois disso, qualquer operação com o proxy lançará umTypeError.

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 é lançadoproxy.foo = 1; // TypeError novamentedelete proxy.foo; // ainda um TypeErrortypeof proxy; // "object", typeof não desencadeia nenhuma trap

Reflexão

Reflect é um objeto embutido que contém métodos que permitem a criação de operações interceptáveis em JavaScript. Os métodos são iguais àqueles deproxy handlers.Reflect não é um objeto do tipo function.

Reflect auxilia no encaminhamento de operações padrão do handler para o target.

Reflect.has(), por exemplo, tem o mesmo efeito prático que o operador in, com a facilidade de ser utilizado como uma função:

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

Uma funçãoapply melhorada

Em ES5, você normalmente utiliza o métodoFunction.prototype.apply() para invocar uma função com um dado valor parathis earguments fornecido como um array (ou umobjeto parecido com um array).

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

ComReflect.apply essa operação se torna menos verbosa e mais fácil 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;// 4Reflect.apply("".charAt, "ponies", [3]);// "i"

Verificando se a definição da propriedade obteve sucesso

ComObject.defineProperty, a qual retorna umobject em caso de sucesso ou lança umTypeError em caso contrário, você utilizaria um blocotry...catch para capturar qualquer erro que tenha ocorrido ao definir uma propriedade. Devido ao fato deReflect.defineProperty retornar um status do tipoBoolean, você pode simplesmente utilizar aqui um blocoif...else:

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

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp