Índice
Em tutoriais anteriores, trabalhamos com classes, tornando nosso aplicativo mais modular, e vimos em profundidade como realizar trabalho assíncrono usando CoffeeScript como linguagem, o que nos dá um leque maior de opções para trabalhar com ela.Tendo dominado esses conceitos, é hora de dar um passo adiante e usar o que sabemos para escrever um código mais limpo, mais funcional e, claro, mais poderoso. É hora de aprender como se tornar usuários avançados de CoffeeScript.
Agora que sabemos como usar classes em nosso aplicativo, é apenas uma questão de tempo antes que tenhamos problemas com ele. contexto. Quando estamos com funções simples é muito fácil ver quais dados esta função possui em seu escopo, ela conhece variáveis globais, variáveis definidas dentro da função e qualquer variável que foi definida no escopo local quando a função foi criada.
Mas quando os métodos são vinculados a objetos, isso fica um pouco mais complicado. Para ilustrar isso, vamos ver um exemplo onde podemos ver este problema e então veremos como CoffeeScript pode nos ajudar:
class Navio içando âncora: (doneCallback) -> console.log "Içando âncora." setVel: (speed) -> console.log "Configurando a velocidade para # {speed}" zarpou: -> @levantarAncla @ fixVel 70Suponha então, de acordo com nosso código, que queremos zarpar imediatamente, para isso fazemos o seguinte para invocar nossa função:
bot = new Barco bot.zarpar ()Se olharmos de perto e transferirmos este código para o mundo real, podemos perceber que o levantamento da âncora não acontece de imediato, devemos esperar que a âncora esteja totalmente levantada para podermos zarpar. Podemos resolver esse problema adicionando um ligue de volta e perguntando se foi concluído, então saberemos quanto tempo leva essa ação e chamaremos nossa função assim que terminar, vamos ver:
liftAnchor: (doneCallback) -> console.log "Levantando âncora." if doneCallback? setTimeout doneCallback, 1000Como podemos ver, só estamos invocando o callback se ele existir, desta forma nos certificamos de que este processo foi concluído e, portanto, devemos modificar nossa função zarpar:
zarpar: -> @levantarAncla -> @ fixVel 70Agora o que fazemos é invocar a função zarpar Depois de levantar a âncora, isso garante que não nos moveremos até que a âncora esteja totalmente levantada. Parece muito bom, vamos compilar nosso código e incluir o arquivo .js gerado em um HTML para ver a resposta do console:
Como podemos ver na imagem, obtivemos um erro onde diz que a função não existe. O que aconteceu? É muito simples, JavaScript definiu o valor Este na forma como a função foi invocada, desde ao chamar bot.zarpar o valor Este está ligado ao objeto robô, então isso está vinculado ao contexto global e não é isso que queremos.
O que queremos fazer é ter certeza de que Este está sempre ligado à instância de robô dentro do corpo do callback e estamos com sorte, pois CoffeeScript tem uma funcionalidade para esse caso. Para isso, declararemos a função com flecha gorda ou seta grossa, desta forma a função terá o Este vinculado ao contexto em que foi declarado, vamos ver como fica nosso código com esta mudança:
class Navio içando âncora: (doneCallback) -> console.log "Içando âncora." if doneCallback? setTimeout doneCallback, 1000 setVel: (speed) -> console.log "Configurando a velocidade para # {speed}" zarpou: -> @levantarAncla => @fixVel 70 bot = new Barco bot.zarpar ()Vamos compilar nosso arquivo e ver como CoffeeScript Vinculação de realização com funcionalidade de seta grossa:
O que faz CoffeeScript antes de declarar o ligue de volta é definir uma variável local _Este, que se refere a Este, uma vez que embora o ligue de volta está dinamicamente vinculado ao valor ainda carrega o contexto local no qual foi declarado. Por fim, vamos executar nosso arquivo gerado e ver como o erro foi resolvido:
Já tendo visto como resolver o problema de contexto em nossos aplicativos com CoffeeScript Veremos uma técnica bastante simples, mas poderosa, para nos ajudar a economizar trabalho. Não é uma técnica avançada, mas é uma maneira lógica de fazer uma melhoria em nosso código sem muito esforço de nossa parte.
MemoizaçãoQual a técnica de memoização é armazenar valores de uma função em vez de recalculá-los cada vez que a função é chamada. Agora que sabemos como usar classes e objetos, podemos usar esse conhecimento para aplicá-los dentro CoffeeScript e usar a técnica em questão.
Existem muitas maneiras de realizar o processo de memoização, para o caso deste tutorial, manteremos as coisas simples. Para isso, o que faremos é que quando forem solicitadas determinadas informações verifiquemos se estão armazenadas, se assim for devolvemos imediatamente, caso contrário podemos calculá-las e guardá-las para uso futuro. Esta técnica é extremamente útil quando precisamos usar um algoritmo complexo para receber uma resposta ou no caso de usarmos uma rede lenta para obter informações.
Então, vamos dar uma olhada no código para ilustrar essa técnica:
classe Rocket getPath: -> @path? = @doMathComplexProcess ()Para explicar melhor esta parte do código, vamos compilá-lo para ver como CoffeeScript construir o JavaScript que nossa técnica terá que nos poupar trabalho em nosso desenvolvimento, vamos ver como nosso código se parece:
PROLONGAR
Como podemos ver em nosso código, o cálculo da trajetória só será realizado na primeira vez que o solicitar e o valor armazenado será usado a partir de agora. Também podemos ver em nosso código CoffeeScript que tivemos a ajuda da operadora terciária ?= que avaliará a expressão caso o caminho seja nulo, além disso teremos ajuda do retorno implícito das funções que retornarão o resultado da expressão, neste caso o valor de @trajetória se foi previamente armazenado ou se acabou de ser calculado.Mas isso não é tudo que podemos fazer com nossa nova técnica em CoffeeScript, podemos até armazenar mais de um valor usando uma estrutura de dados, vamos ver como podemos fazer isso:
class SecurityGateway hasAccess: (guard) -> @access? = {} @access [guard.plate_number]? = verifyCredentials guard.plate_numberO que esta parte do código faz é que em nosso objeto o resultado é armazenado para cada guarda que solicitou acesso, nós só precisaríamos de algo único para poder identificá-los em nosso objeto, então usamos o número da placa para esta tarefa, vamos ver como nosso código é traduzido quando o compilamos:
PROLONGAR
É importante mencionar que esta técnica só deve ser utilizada com informações que não sofrerão alterações durante a execução do nosso programa, caso o seja, recomendamos implementar uma solução baseada em esconderijo.Finalmente, veremos uma maneira de passar opções para uma função, esta não é uma funcionalidade especial do CoffeeScriptÉ mais uma convenção que faz uso de muitas das características da língua, usando-as em um padrão que é fácil de entender e que é igualmente útil em muitas situações que podem surgir.
Como funciona?A ideia por trás disso é simples, é ter uma função que aceite esta objeto de opções que pode conter chaves associativas para os argumentos dessa função. Isso torna as opções fáceis de entender a partir do código no qual estão sendo chamadas, porque existem chaves para identificar o que cada valor faz. Isso também reduz o incômodo de ficar de olho nos argumentos e também em sua ordem, uma vez que as chaves de objeto não dependem disso e podem ser omitidas se não forem necessárias.
Para implementar o objetos de opções primeiro vamos usar argumentos opcionais como padrão para um argumento vazio. Desta forma, ao fazer a chamada, podemos omitir as opções caso os valores não sejam necessários:
launchNave = (nome, opções = {}) -> retornar se options.drift dry take off ()Agora vamos usar o operador terciário ?= para preencher os valores das opções para as quais queremos um valor padrão especial:
launchNave = (nome, opções = {}) -> options.count? = 10 console.log "# {i}…" para i em [options.count… 0] retornar se options.drift dry take off ()Definimos um último valor e usamos o operador ? caso seja usado em um só lugar:
launchSave = (nome, opções = {}) -> checkFuel (options.waitComb? 100) options.count? = 10 console.log "# {i}…" para i em [options.count… 0] retornar se opções. decolagem a seco ()Finalmente, aproveitamos a sintaxe permissiva de CoffeeScript para enviar as opções para nossa função sem os colchetes, nos dando uma chamada bastante simples e natural:
launchShip "Millennium Falcon", DryGear: verdadeiro, contagem regressiva: 15Para terminar, vamos compilar nosso arquivo e ver a saída de nosso código em JavaScript:
PROLONGAR
Com o último terminamos este tutorial, onde pudemos aprender não apenas formas avançadas de usar CoffeeScript mas sim técnicas que nos ajudarão a escrever um código melhor, que com uso e pesquisa constantes, podemos nos tornar melhores desenvolvedores que usam as melhores práticas para desenvolver aplicativos.