Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Duvida retorno acao(target)

Pessoal, Me parece que a duvida em relação a este ponto não é nova, li os outros topicos e mesmo assim ainda a duvida permanece.

Quando passo a instrução abaixo para a variavel acao o valor dela passa a ser:

model=>this._listaNegociacoesView(model);

quando chega na instrução return acao(target) o que acontece por baixo dos panos? Como é possivel envolver o target entre parenteses no valor da variavel acao? Neste exato momento antes do return o valor de acao passar a ser o que?

este ponto ficou meio confuso :(

obrigado pela ajuda, abs

6 respostas
solução!

Vamos lá meu amigo!

Parece um pouco confuso porque várias coisas estão acontecendo neste momento, vou tentar separar em partes para facilitar o seu entendimento e o meu kkk:

  • Lá na classe Bind você define que "acao" é uma função pré-definida que sempre vai esperar um "model" como parâmetro. Um ponto importante é que sempre que essa função for executada o "this" dela será o this da view que você passou como parâmetro pois utilizamos uma arrow function, ok até aqui?

  • Lá na classe ProxyFactory quando você dá o return em "acao(target)" você está invocando aquela função definida em Bind, que espera um parâmetro, no caso um model para alimentar a função de atualização da View. Relembrando o uso do proxy de JS, o seu target no caso é o objeto que você envolveu com o proxy, que é o model, blz? Como a função definida em Bind espera um model, ao invocar "acao(target)", você está invocando aquela função e passando o model (target) como parâmetro.

  • A variável "acao" que foi passada para a ProxyFactory contém internamente uma função, aquela que vai chamar o update da view. Pelo fato desta variável ser uma função, dentro de ProxyFactory iremos invocar esta função passando o nosso model como argumento. O que talvez tenha te deixado um pouquinho consufo aqui é que Javascript permite passarmos funções como argumentos de métodos, "acao" é uma variável que aponta para uma funcão, por esse motivo que invocamos a função chamando "acao(target)" dentro de ProxyFactory.

  • Exemplo:

let acao = function(texto) {
    console.log("Hello " + texto);
};

acao("world");

Se executar o código acima verá "Hello world" no seu console, veja que definimos uma função para uma variável e abaixo invocamos esta função passando um parâmetro.

Só para tentar ajudar mais, segue o trecho do ProxyFactor com os nomes dos parâmetros trocados apenas para ilustrar o que estou dizendo:

get(modelQueFizemosProxy,
     propriedadeQueEstamosInterceptando, 
     proxyEmSi) {

    /*Aqui testamos se a propriedade que está sendo ativada pela chamada ao Proxy faz parte das
      propriedades que queremos monitorar e se essa propriedade é uma função.*/
    if (props.includes(propriedadeQueEstamosInterceptando)
    && ProxyFactory._ehFuncao(modelQueFizemosProxy[propriedadeQueEstamosInterceptando])) {

        /*Se for uma função neste momento precisamos fazer duas coisas, primeiro substituir a
          função original pela nossa função modificada e segundo, garantir que a função original também seja chamada.*/        
        return function () {

            /*Aqui fazemos com que a função original seja invocada e o seu resultado armazenado na variável "retorno"*/
            let retorno = Reflect.apply(modelQueFizemosProxy[propriedadeQueEstamosInterceptando], modelQueFizemosProxy, arguments);

            /*Aqui executamos a função definida lá na classe Bind, que foi passada como argumento para a criação do 
              nosso Proxy sob a variável "acao", é neste momento que passamos o target (model) para que a função ao 
              executar, receba o nosso model como parâmetro,*/
            acao(modelQueFizemosProxy);

            /*Por fim retornamos a quem chamou a função, o retorno original do método do nosso modelo que está 
              encapsulado pelo proxy.*/
            return retorno;
        };
    }

    /*Caso a propriedade invocada no proxy não seja nenhuma das que estamos monitorando ou não seja uma função, 
      com a instrução abaixo deixamos que o curso normal da execução siga em frente.*/
    return Reflect.get(modelQueFizemosProxy, propriedadeQueEstamosInterceptando, proxyEmSi);

}

Ficou claro agora? Se ainda não ficou claro, tente dividir um pouco as dúvidas em pontos distintos que a gente tenta esclarecer um por vez.

Espero ter ajudado, abraço!

Bruno, sua explicação tem o capricho de um cangaceiro JavaScript. Tiro o chapéu, parabéns!

Andpaip, Bruno conseguiu elucidar a questão? Se sim, marque a resposta dele como solução porque ele merece os pontos.

E vamos avançar no cangaço da programação!

Boa tarde Bruno,

Não só pra mim mas acredito que para o conteúdo do curso, nós alunos agradecemos demais o tempo que você disponibilizou para se dispor a ajudar. De verdade muito obrigado. Vou tentar ser mais claro na duvida: No caso em que relato aqui, ainda nem criei a classe Bind. Veja no capitulo 1 deste modulo que acabamos de criar a classe ProxyFactory:

class ProxyFactory {

    static create(objeto, props, acao) {

        return new Proxy(objeto, {

            get(target, prop, receiver) {

                if(props.includes(prop) && typeof(target[prop]) == typeof(Function)) {
                    return function() {

                        console.log(`a propriedade "${prop}" foi interceptada`);
                        Reflect.apply(target[prop], target, arguments);
                        return acao(target);
                    }
                }
                return Reflect.get(target, prop, receiver);       
            }
        })
    }
}

E neste momento ajustamos o codigo do NegociaçãoController:

this._listaNegociacoes = ProxyFactory.create (
    new ListaNegociacoes(),
    ['adiciona', 'esvazia'], model =>
        this._negociacoesView.update(model));

Veja que neste momento a variavel "acao" lá do ProxyFactory passa a valer:

model=>this._negociacoesView.update(model)

nao consegui visualizar o exato momento em que a função é executada. O target é o nosso objeto, beleza, mais o valor de acao é

model=>this._listaNegociacoesView.update(model)

onde esse target se encaixa ai dentro rsrs.. sei lá ..

mais ai veio a magicá.. kk.. acho que como vinhamos usando nos cursos anteriores bastante a arrow function mais em loops de arrays, etc.. chegou aqui deu um nó no cerebro.. kk.. o que me parecia ser uma duvida complexa agora ficou extremamente claro e parece uma duvida meio idiota.. kkkk... seu exemplo foi perfeito pra desenrolar o nó..

ja vimos anteriormente que:

model=>this._listaNegociacoesView.update(model)

é igual a isso

function(model){
    this._listaNegociacoesView(model);
}

que virou isso (atentando para que quando é arrow function o this passa a ser NegociacaoController)

acao(target){
    this._listaNegociacoesView(target);
}

logico que quando você chamar acao(target) o target é o parametro da função. rsrs

p.. m.. kkkk que burrico da 0 pra mim.. kk..

deu até vergonha na duvida agora kkk.. mas sem crise.. desconfio que vai ajudar outras pessoas.. valeu mesmo meu velho. abração

Fala Andpaip!

Que bom que agora sua dúvida foi resolvida! Cara, não existem dúvidas idiotas, agora está simples e claro pra você porque você entendeu, não porque a sua dúvida não era genuína, não pense assim não, é normal e saudável ter dúvidas, sinal de que você está se preocupando em aprender de verdade, não apenas em copiar o que vê na tela sem saber o porque das coisas.

Precisando é só chamar!

Professor Flávio, é uma honra pra mim ser chamado de cangaceiro pelo Lampião do Javascript! Se eu pude ajudar o colega aqui é porque tive um bom professor, como o senhor!

Abraço a todos e até breve!

Concordo com Bruno, tem que perguntar mesmo. Se ficarem dúvidas, elas vão se acumulando, se acumulando e no final fica tudo mais difícil.

Bruno, obrigado pelo feedback. Espero trazer mais novidades para a Alura (ideias não faltam).

Andpaip, sente vergonha não!

Eu tive a mesma dúvida e a sua elucidação que me salvou!

Abração!!!