Acesse nosso Fórum

JavaScript com café

Conheça a linguagem CoffeeScript que, diferente dos frameworks e bibliotecas, compila código JavaScript puro ao invés de ser apenas mais uma camada sobre a linguagem.

por Davi Ferreira 09/04/2012 Comentários

CoffeeScript é uma tentativa de tornar JavaScript mais agradável para nós, programadores.

Diferente dos frameworks e bibliotecas, que foram desenvolvidos como uma camada extra, o código escrito em CoffeeScript é compilado e resulta em JavaScript puro.

A sintaxe é inspirada em linguagens como Ruby e Python (principalmente Ruby), portanto você pode esperar códigos intuitivos e limpos, sem pontos-e-vírgulas, chaves e parênteses (quase).

Instalação & Comandos

Não vou entrar muito em detalhes sobre a instalação da linguagem. A maneira mais fácil de instalar as ferramentas para desenvolvimento em CoffeeScript é através do sistema de pacotes do NodeJS, o npm.

[cce lang=”bash”]npm install -g coffee-script[/cce]

O criador do npm disponibilizou um gist com instruções variadas para a instalação do NodeJS e seu gerenciador de pacotes.

Depois de seguir todos os passos necessários, para conferir se a instalação foi concluída com sucesso, digite o seguinte comando em um terminal:

[cce lang=”bash”]coffee -v[/cce]

O comando coffee, executado via terminal, pode ser utilizado como um console interativo, como um compilador ou como um watcher. Como um watcher, o comando vigia qualquer alteração em códigos-fonte CoffeeScript e, automaticamente, gera os arquivos JavaScript.

[cce lang=”bash”]# executa o console

coffee

# compila o arquivo codigo.coffee para codigo.js

coffee -c codigo.coffee

# compila o arquivo codigo.coffee para script.js

coffee -co script.js codigo.coffee

# observa os arquivos no diretório coffeescripts e compila para o diretório javascripts

coffee -cwo javascripts coffeescripts[/cce]

Além disso, ele pode também executar diretamente um script:

[cce lang=”bash”]coffee codigo.coffee[/cce]

Uma maneira mais fácil de testar e experimentar CoffeeScript é visitando o link “Try CoffeeScript” no site oficial da linguagem. Lá você pode observar, em tempo real, o resultado da transformação de CoffeeScript em JavaScript.

Variáveis & Funções

A simplificação começa com a declaração de variáveis, eliminando a necessidade de instanciá-las:

[cce lang=”coffeescript”]mensagem = “Olá, Tableless!”

alert mensagem[/cce]

O código acima resulta no seguinte JavaScript:

[cce lang=”javascript”]var mensagem;

mensagem = “Olá, Tableless!”;

alert(mensagem);[/cce]

Já uma função em CoffeeScript é representada pela junção dos caracteres “-” e “>”:

[cce lang=”coffeescript”]cafe = -> “Café!”[/cce]

JavaScript:

[cce lang=”javascript”]var cafe;

cafe = function() {

return “Café!”;

};[/cce]

O compilador CoffeeScript vai sempre transformar suas funções em expressões, ou seja, funções armazenadas em variáveis.

Vale lembrar que assim como em Python, a indentação em CoffeeScript precisa ser seguida à risca. Seu código deve respeitar um padrão de indentação — tab ou espaços, nunca os dois ao mesmo tempo.

O valor retornado por uma função é sempre a última linha de sua implementação. Não é necessário utilizar return.

Os argumentos devem ser declarados antes do símbolo da função. A concatenação segue o estilo Ruby de ser:

[cce lang=”coffeescript”]cafe = (sabor) -> “Quero café #{sabor}!”[/cce]

JavaScript:

[cce lang=”javascript”]var cafe;

cafe = function(sabor) {

return “Quero café ” + sabor + “!”;

};[/cce]

Eles podem ainda possuir valores padrões, caso não seja passado nenhum parâmetro:

[cce lang=”coffeescript”]cafe = (sabor = “forte”) -> “Quero café #{sabor}!”[/cce]

E, como já deu pra perceber, quando uma função é chamada, os parênteses são opcionais:

[cce lang=”coffeescript”]cafe(“suave”)

cafe “suave”

[1, 2, 3, 4].slice(0, 1)

[1, 2, 3, 4].slice 0, 1[/cce]

Objetos

Existem duas maneiras de representar objetos em JavaScript. A primeira é utilizando new:

[cce lang=”javascript”]pessoa = new Pessoa();[/cce]

A maneira mais comum, no entanto, é utilizando a notação JSON:

[cce lang=”javascript”]pessoa = {};[/cce]

Este tipo de criação é simplificado no CoffeeScript, com a remoção das chaves e vírgulas, utilizando apenas indentação para formatar o objeto:

[cce lang=”coffeescript”]autor =

nome: “Davi Ferreira”

especialidades: [“javascript”, “jquery”]

sites:

blog: “http://www.daviferreira.com/blog"

portfolio: “http://www.daviferreira.com"

social:

twitter: “davitferreira”[/cce]

Agora o mesmo objeto, em JavaScript:

[cce lang=”javascript”]var autor;

autor = {

nome: “Davi Ferreira”,

especialidades: [“javascript”, “jquery”],

sites: {

blog: “http://www.daviferreira.com/blog",

portfolio: “http://www.daviferreira.com"

},

social: {

twitter: “davitferreira”

}

};[/cce]

Operações condicionais e comparativas

As operações condicionais em CoffeeScript são bastante flexíveis e mais poderosas do que as operações nativas em JavaScript. O CoffeeScript introduz novos tipos de implementações de operações condicionais:

[cce lang=”coffeescript”]alert “Frio” if temperatura < 20[/cce]

[cce lang=”coffeescript”]if temperatura < 20 then alert “Frio” else alert “Calor”[/cce]

O segundo exemplo, compilado, fica assim:

[cce lang=”javascript”]if (temperatura < 20) {

alert(“Frio”);

} else {

alert(“Calor”);

}[/cce]

Os operadores também receberam uma repaginada, ganhando versões “escritas”:

[cce lang=”coffeescript”]if temperatura < 20 and cidade is “Rio de Janeiro” then alert “Frio”[/cce]

[cce lang=”coffeescript”]if alarme is on and not snooze and hora is “09:00” then alert “Beep!”[/cce]

Javascript:

[cce lang=”javascript”]if (alarme === true && !snooze && hora === “09:00”) alert(“Beep!”);[/cce]

Outra implementação legal é a comparação em cadeia:

[cce lang=”coffeescript”] if 12 < idade < 18 then alert “Adolescente”[/cce]

Javascript:

[cce lang=”javascript”] if (12 < idade && idade < 18) alert(“Adolescente”);[/cce]

Loops

Antes de falar sobre operações de loop, vamos conhecer ranges ou intervalos. Em CoffeeScript é possível declarar ranges dinâmicos:

[cce lang=”coffeescript”]horas = [0..24][/cce]

O código acima gera a lista completa, de 0 a 24. O resultado ainda pode ser trabalhado retornando apenas os quatro primeiros valores (0, 1, 2, 3):

[cce lang=”coffeescript”]horas[0..3] [/cce]

A manipulação de dados via loops é bem completa, com diferentes possibilidades:

[cce lang=”coffeescript”]times = [“Flamengo”, “Vasco”, “Botafogo”, “Fluminense”]

for time in times

alert “Time: #{time}”[/cce]

O código acima resulta no seguinte JavaScript (!):

[cce lang=”javascript”]var time, times, _i, _len;

times = [“Flamengo”, “Vasco”, “Botafogo”, “Fluminense”];

for (_i = 0, _len = times.length; _i < _len; _i++) {

time = times[_i];

alert(“Time: “ + time);

}[/cce]

Outra maneira de executar um loop é declarando tudo em uma única linha:

[cce lang=”coffeescript”]alert “Time: #{time}” for time in times[/cce]

Podemos ainda manipular os dados diretamente no loop:

[cce lang=”coffeescript”]alert “#{time} – RJ” for time in times[/cce]

E para finalizar essa parte sobre loops, uma ferramenta muito útil é a keyword when, utilizada para filtrar os dados do loop:

[cce lang=”coffeescript”]alert “Segunda divisão!” for time in times when time isnt “Flamengo”[/cce]

Integração com jQuery

Escrever código em CoffeeScript não significa abandonar bibliotecas e frameworks JavaScript. A integração com CoffeeScript é direta:

[cce lang=”coffeescript”]$ -> [/cce]

Equivale a:

[cce lang=”javascript”]$(function() {});[/cce]

A premissa básica continua sendo a simplificação do código, principalmente devido a remoção de chaves, parênteses, vírgulas e pontos-e-vírgulas.

[cce lang=”coffeescript”]$(window).konami ->

$(“html”).addClass “tremetudo”[/cce]

O código acima é a implementação do Konami Code aqui no Tableless.

Veja o JavaScript original:

[cce lang=”javascript”]$(window).konami(function(){

$(“html”).addClass(“tremetudo”)

});[/cce]


Essa foi uma visão geral da linguagem. A desvantagem de implementar CoffeeScript em produtos e aplicativos grandes é o fato de ainda ser difícil debugar o código diretamente, já que as ferramentas disponíveis nos navegadores só indicam os erros no arquivo JavaScript gerado. O compilador aponta os erros de sintaxe, mas erros de lógica dão um pouco mais de trabalho.

Muitos aspectos ficaram de fora deste artigo, como os splats, escopo, propriedades, switches, soaks e, principalmente, classes. No próximo artigo falo mais sobre eles.