Prefácio
No ES6, o construtor de proxy é um objeto global acessível, usando -o, você pode coletar várias informações sobre operações solicitadas entre o objeto e o comportamento de vários objetos de operação e retornar o que quiser. As funções de seta, desconstrução da matriz, parâmetros de descanso e outros recursos no ES6 foram amplamente divulgados depois de implementados, mas recursos como proxy raramente são vistos pelos desenvolvedores. Por um lado, é por causa da compatibilidade do navegador e, por outro lado, é por causa das vantagens desses recursos que os desenvolvedores precisam entender profundamente seus cenários de uso. Pessoalmente, eu realmente gosto do proxy do ES6 porque nos permite controlar o acesso externo a objetos de uma maneira concisa e fácil de entender. A seguir, primeiro introduzirei como o proxy é usado e, em seguida, listarei exemplos específicos para explicar os cenários de uso do proxy.
Proxy , veja o nome e o significado, tem uma função muito semelhante ao modo proxy no modo de design, que é frequentemente usado em três aspectos:
1. Monitore o acesso externo a objetos
2. Função ou complexidade de classe
3. Verifique a operação ou gerencie os recursos necessários antes da operação
Em um ambiente de navegador que suporta proxy, o proxy é um objeto global que pode ser usado diretamente. Proxy(target, handler) é um construtor, target é o objeto que está sendo processado e handlder é um objeto que declara várias operações de proxy e, finalmente, retorna um objeto de proxy. Toda vez que o mundo exterior acessa as propriedades do objeto target através do objeto Proxy, ele passa pelo objeto handler . A partir desse processo, o objeto proxy é muito semelhante ao middleware (middleware). Então, quais operações podem interceptar proxy? As operações mais comuns são Get (Read), Set (Modify) Propriedades do objeto, etc. Por favor, clique aqui para obter uma lista completa de operações interceptáveis. Além disso, o objeto Proxy também fornece um método revoke que pode registrar todas as operações de proxy a qualquer momento. Antes de apresentar formalmente proxy, recomendamos que você tenha um certo entendimento de refletir, que também é um novo objeto global adicionado ao ES6.
Básico
const target = {nome: 'billy bob', idade: 15}; const handler = {get (alvo, chave, proxy) {const Today = new Date (); console.log (`obtenha solicitação feita para $ {key} em $ {Today}`); retorno reflete.get (destino, chave, proxy); }}; const proxy = new Proxy (Target, manipulador); proxy.name; // => "Obtenha a solicitação feita para nome em qui 21 de julho de 2016 15:26:20 gmt+0800 (cst)" // => "billy bob" No código acima, primeiro definimos um objeto target a ser proxyed e, em seguida, declaramos um objeto handler contendo todas as operações de procuração. Em seguida, usamos Proxy(target, handler) para criar o proxy do objeto proxy. Depois disso, todos os acessos ao atributo target usando proxy serão processados pelo handler .
1. Saia do módulo de verificação
Vamos começar com uma simples verificação de tipo, que demonstra como usar o proxy para garantir a precisão dos tipos de dados:
Deixe numericDataStore = {count: 0, quantidade: 1234, Total: 14}; numericDataStore = novo proxy (numericDataStore, {set (Target, chave, valor, proxy) {if (typeof value! }}); // um erro foi lançado porque "foo" não é um numericDataStore.count = "foo"; // atribuído com sucesso numericDatastore.count = 333;Se você deseja desenvolver um verificador diretamente para todas as propriedades de um objeto, ele pode rapidamente tornar a estrutura de código inchada, usando proxy, você pode separar o verificador da lógica do núcleo e entrar em um:
função Createvalidator (Target, Validator) {Retorne novo proxy (Target, {_Validator: Validator, Set (Target, Key, Value, Proxy) {if (Target.HasownProperty (key)) {Let Valdalator = TOT._Validator [key]; se (Chap) {) {Let Reflator.Set.Set._Validator [key]; se (!! protiltator (value)) {retirt.Set.Set.Set. $ {key} para $ {value}. }, idade (val) {return typeof Age === 'Número' && Age> 18; }} classe Person {construtor (nome, idade) {this.name = name; this.age = idade; Retornar Createvalidator (isto, Pessoa Validadores); }} const bill = new Pessoa ('Bill', 25); // As seguintes operações relatarão uma fatura de erro.name = 0; bill.age = 'Bill'; bill.age = 15; Através da separação do verificador e da lógica principal, você pode estender infinitamente o conteúdo do verificador personValidators sem causar danos diretos às classes ou funções relevantes. Para ser mais complicado, também podemos usar proxy para simular a verificação do tipo para verificar se a função recebe parâmetros com tipo e quantidade corretos:
Seja obj = {pickymethone: function (obj, str, num) { / *... * /}, pickymethodtwo: function (num, obj) { / *... * /}}; const argtypes = {pickyMethodOne: ["objeto", "," número "], pickymethodtwo:" {get: function (chave, proxy) {var value = Target [Key]; function argchecker (nome, args, verificadores) {for (var idx = 0; idx <args.length; idx ++) {var arg = args [idx]; var tipo = verificações [idx]; if (! arg || typeof arg! == type) {console.warn (`você está implementando incorretamente a assinatura de $ {name}. verifique o param $ {idx + 1}`); }}} obj.pickymethodOne (); //> Você está implementando incorretamente a assinatura de PickyMetodOne. Verifique o param 1 //> você está implementando incorretamente a assinatura do pickymetodona. Verifique o param 2 //> você está implementando incorretamente a assinatura do pickymetodona. Verifique o param 3obj.pickymethodtwo ("wopdapodoo", {}); //> Você está implementando incorretamente a assinatura de PickyMetodOne. Verifique o param 3obj.pickymethodtwo ("wopdapodoo", {}); //> Você está implementando incorretamente a assinatura de PickyMetodOne. Verifique o param 3obj.pickymethodtwo ("wopdapodoo", {}); //> Você está implementando incorretamente a assinatura de pickymethodtwo. Verifique o param 1 // sem avisos loggedobj.pickymethodone ({}, "uma pequena string", 123); obj.pickyMethodOne (123, {});2. Atributos privados
No JavaScript ou em outros idiomas, é habitual adicionar um _ antes do nome da variável para indicar que essa é uma propriedade privada (não realmente privada), mas não podemos garantir que ninguém o acessará ou modificará. No código a seguir, declaramos um apiKey privado para facilitar as chamadas de método dentro do objeto api , mas não queremos acessar api._apiKey de fora:
var api = {_apikey: '123ABC456DEF',/ * MOME MÉTODOS que usam isso._apikey */ getUsers: function () {}, getUser: function (userId) {}, setUser: function (userId, config) {}}; // logs '123BC46d) api._apikey); // obtenha e muta _apikeys conforme desejado apikey = api._apikey; api._apikey = '987654321';Obviamente, a convenção é irrestrita. Usando o proxy ES6, podemos implementar variáveis privadas reais. O seguinte demonstra dois métodos privados diferentes para diferentes métodos de leitura.
O primeiro método é usar o conjunto/interceptar solicitações de leitura e gravação e retornar undefined:
let api = { _apiKey: '123abc456def', getUsers: function(){ }, getUser: function(userId){ }, setUser: function(userId, config){ }};const RESTRICTED = ['_apiKey'];api = new Proxy(api, { get(target, key, proxy) { if (restrito.indexOf (key)> -1) {TRABELAR ERRO (`$ {key} é restrito. Consulte a documentação da API para obter mais informações. info.`);O segundo método é usar a interceptação em operação:
var api = {_apikey: '123ABC456DEF', getUsers: function () {}, getUser: function (userID) {}, setUser: function (userID, config) {}}; const Restrits = ['_apikey']; Api = new (} (API, {{haspikey ']; -1)? Proxy obscurece _apikey ... ")}}3. Log de acesso
Para atributos ou interfaces que frequentemente chamam, executam lentamente ou ocupam mais recursos no ambiente de execução, os desenvolvedores desejam registrar seu uso ou desempenho. No momento, eles podem usar proxy para atuar como middleware e implementar facilmente a função de registro:
Seja api = {_apikey: '123ABC456DEF', getUsers: function () { / * ... * /}, getUser: function (userID) { / * ... * /}, SetUser: function (userId, config) { / * /}}; function) (se setTethSyn (userId, config) { / * ... * /}}; Console.log (`$ {Timestamp} - log $ {Method} Solicitação assíncrona. };}}); api.getUsers ();4. Aviso e interceptação precoce
Suponha que você não queira que outros desenvolvedores excluam o atributo noDelete e queira que os desenvolvedores que chamam oldMethod entendem que esse método foi abandonado, ou diga aos desenvolvedores que não modifiquem doNotChange , então você pode usar o proxy para implementá -lo:
Seja DataStore = {NodElete: 1235, OldMethod: function () {/*...*/}, DONOTHANGE: "Tentado e verdadeiro"}; const nodelete = ['nodelete']; const nochange = ['Donotchange']; const depreciado = ['OldMethod']; DataStore = new Proxy (DataStore, {Set (Target, Key, Value, Proxy) {if (nochange.includes (key)) {THR ERRO (`Error! $ {key} é imutável. Erro (erro! $ {Key} não pode ser excluído. function (... args) {reflete.Apply (Target [Key], Target, Args); excluir datastore.nodelete; DataStore.oldMethod ();5. Operação do filtro
Algumas operações adotam muito recursos, como transferir arquivos grandes. No momento, se o arquivo já for enviado em pedaços, não há necessidade de tornar correspondente (não absoluto) para a nova solicitação. No momento, você pode usar o proxy para detectar o recurso da solicitação e filtrar quais não precisam responder e quais precisam responder de acordo com os recursos. O código a seguir demonstra brevemente como filtrar os recursos, não o código completo. Eu acredito que todos vão entender as coisas maravilhosas:
Seja obj = {getGiantFile: function (FILEID) {/*...*/}}; obj = novo proxy (obj, {get (alvo, chave, proxy) {return function (... args) {const iD = args [0]; let iSenRooute = checkenRoute (id); (ISENROUTE || IsDownload) {return false;6. Agente de interrupção
O proxy suporta a desbroxi para target a qualquer momento, que geralmente é usada para incluir o acesso completamente a dados ou interfaces. No exemplo a seguir, usamos o método Proxy.revocable para criar um objeto de proxy que proxies recantravelmente:
Seja sensitivedata = {nome de usuário: 'devBryce'}; const {sensitivedata, revogação} = proxy.revocable (sensitivedata, manipulador); function )eSeSeDHack () {revokeccess ();} // Logs 'devBryce'Console.Console.Console.Console.; HandleSuspeedHack (); // typeError: revogedconsole.log (sensitivedata.username);Decorador
O decorador implementado no ES7 é equivalente ao modo decorador no modo de design. Se você simplesmente distinguir os cenários de uso de proxy e decorador , ele pode ser resumido como: A função central do proxy é controlar o acesso do mundo externo ao agente, e a função central do decorador é aprimorar as funções do decorador. Desde que façam uma boa diferença em seus principais cenários de uso, funções como logs de acesso, embora este artigo use implementação de proxy, eles também podem ser implementados usando o decorador. Os desenvolvedores podem escolher livremente com base nas necessidades do projeto, especificações da equipe e suas próprias preferências.
Resumir
A proxy do ES6 ainda é muito prática. Suas características aparentemente simples são de grande utilidade. Espero que seja útil para todos aprenderem o ES6.