CoffeeScript é uma pequena linguagem que compila para JavaScript. Por baixo de todas essas chaves e ponto-e-vírgulas inconvenientes, JavaScript sempre teve um lindo modelo de objeto em seu coração. CoffeeScript é uma tentativa de expor as partes boas de JavaScript de uma maneira simples.
A regra de ouro do CoffeeScript é: "É apenas JavaScript". O código compila para um JS equivalente, e não há uma interpretação em tempo de execução (runtime). Você pode usar qualquer biblioteca JavaScript existente com CoffeeScript sem problemas (e vice-versa). A saída compilada é legível e bem impressa, passa pelo JavaScript Lint sem advertências, funcionará em qualquer runtime JavaScript, e tende a executar tão ou mais rápido que o JavaScript equivalente escrito a mão.
Versão Mais Recente: 1.3.3
Traduzido para o português por Loop Infinito (@loopinfinito).
CoffeeScript à esquerda, saída compilada de JavaScript à direita.
# Atribuições: number = 42 opposite = true # Condições: number = -42 if opposite # Funções: square = (x) -> x * x # Arrays: list = [1, 2, 3, 4, 5] # Objetos: math = root: Math.sqrt square: square cube: (x) -> x * square x # Splats: race = (winner, runners...) -> print winner, runners # Teste de existência: alert "I knew it!" if elvis? # Compreensões de Arrays: cubes = (math.cube num for num in list)
var cubes, list, math, num, number, opposite, race, square, __slice = [].slice; number = 42; opposite = true; if (opposite) { number = -42; } square = function(x) { return x * x; }; list = [1, 2, 3, 4, 5]; math = { root: Math.sqrt, square: square, cube: function(x) { return x * square(x); } }; race = function() { var runners, winner; winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners); }; if (typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); } cubes = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = list.length; _i < _len; _i++) { num = list[_i]; _results.push(math.cube(num)); } return _results; })();
O próprio compilador CoffeeScript é escrito em CoffeeScript, usando o gerador de analisador (parser) Jison. A versão linha de comando coffee está disponível como um utilitário Node.js. O compilador entretanto, não depende do Node, e pode ser executado em qualquer ambiente JavaScript, ou no navegador (veja "Experimente CoffeeScript", acima).
Para instalar, primeiramente tenha certeza de que tem uma cópia da última versão estável do Node.js, e do npm (o Gerenciador de Pacotes do Node – Node Package Manager). Você então poderá instalar o CoffeeScript com o npm:
npm install -g coffee-script
(Deixe de fora o -g caso não queira instalar globalmente.)
Se preferir instalar a versão mais recente do CoffeeScript, você pode clonar o repositório do código fonte do CoffeeScript no GitHub, ou fazer o download do código fonte diretamente. Para instalar o compilador CoffeeScript para todo o sistema em /usr/local, abra o diretório e execute:
sudo bin/cake install
Depois de instalado, você deverá ter acesso ao comando coffee, que pode executar scripts, compilar arquivos .coffee para .js, e fornecer um REPL (Read-Eval-Print-Loop) interativo. O comando coffee aceita as seguintes opções:
-c, --compile |
Compila um script .coffee para um arquivo JavaScript .js com o mesmo nome. |
-i, --interactive |
Inicia uma sessão interativa de CoffeeScript para execução de pequenos trechos. Idêntico ao chamar coffee sem argumentos. |
-o, --output [DIR] |
Escreve todos os aquivos JavaScript compilados no diretório especificado. Use em conjunto com --compile ou --watch. |
-j, --join [FILE] |
Antes de compilar, concatena todos os scrips juntos na mesma ordem em que forem passados, e os escreve no arquivo especificdo. Útil na construção de grandes projetos. |
-w, --watch |
Observa os arquivos por modificações, reexecutando o comando especificdo quando qualquer arquivo for atualizado. |
-p, --print |
Em vez de escrever o JavaScript como um arquivo, imprime diretamente na saída padrão (stdout). |
-l, --lint |
Se o comando jsl
(JavaScript Lint)
está instalado, use-o para verificar a compilação de um
arquivo CoffeeScript. (Conveniente em conjunto com --watch) |
-s, --stdio |
Passa o CoffeeScript para STDIN e recupera o JavaScript pela STDOUT.
Bom para uso com processos escritos em outras linguagens. Por exemplo: cat src/cake.coffee | coffee -sc |
-e, --eval |
Compila e imprime um pequeno fragmento de CoffeeScript diretamente da
linha de comando. Por exemplo: coffee -e "console.log num for num in [10..1]" |
-r, --require |
Carrega uma biblioteca antes de compilar ou executar seu script. Pode ser usado para ligar algo ao compilador (para adicionar notificações Growl, por exemplo). |
-b, --bare |
Compila o JavaScript sem a função de segurança de alto nível. |
-t, --tokens |
Em vez de realizar a análise sintática (parse) do CoffeeScript, apenas realiza a analise léxica e imprime o fluxo de tokens: [IDENTIFIER square] [ASSIGN =] [PARAM_START (] ... |
-n, --nodes |
Em vez de compilar o CoffeeScript, apenas realiza as análises léxica e sintática,
e imprime a árvore sintática:
Expressions Assign Value "square" Code "x" Op * Value "x" Value "x" |
--nodejs |
O executável node tem algumas opções úteis que você pode especificar, como --debug, --debug-brk e --max-stack-size. Use esta flag para passar as opções diretamente ao Node.js. |
Exemplos:
Esta referência está estruturada de maneira que possa ser lida de cima para baixo, se desejar. Ao decorrer do documento, as seções usam idéias e sintaxes anteriormente introduzidas. É necessário ter familiaridade com JavaScript. Em todos os exemplos seguintes, o código CoffeeScript é fornecido ao lado esquerdo, e a compilação direta para JavaScript está ao lado direito.
Muitos dos exemplos podem ser executados (os que fazem sentido), pressionando o botão executar à direita, e pode ser carregado no console "Experimente CoffeeScript" pressionando o botão carregar do lado esquerdo.
Primeiramente, o básico: CoffeeScript usa espaços em branco para delimitar blocos de código. Você não precisa usar ponto-e-vígulas ; ao término de uma expressão, terminar a linha terá o mesmo resultado (embora ainda seja possível utilizar ponto-e-vírgula para delimitar várias expressões em uma mesma linha). Em vez de usar chaves { } para agrupar blocos de código em funções, if, switch, e try/catch, use indentação.
Você não precisa usar parênteses para invocar uma função se você estiver
passando argumentos. A chamada agrupa implicitamente até o fim da linha ou da expressão de bloco.
console.log sys.inspect object → console.log(sys.inspect(object));
Funções Funções são definidas por uma lista de parâmetros opcionais entre parênteses, uma seta, e o corpo da função. A função vazia parece assim: ->
square = (x) -> x * x cube = (x) -> square(x) * x
var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; };
Funções também podem ter valores padrão para argumentos. Sobrescreva o valor padrão passando um argumento não nulo.
fill = (container, liquid = "coffee") -> "Filling the #{container} with #{liquid}..."
var fill; fill = function(container, liquid) { if (liquid == null) { liquid = "coffee"; } return "Filling the " + container + " with " + liquid + "..."; };
Objetos e Arrays Os literias de CoffeeScript para objetos e arrays se parecem bastante com seus primos JavaScript. Quando cada propriedade é listada em sua própria linha, as vírgulas são opcionais. Objetos devem ser criados usando indentação em vez de chaves explícitas, similar ao YAML.
song = ["do", "re", "mi", "fa", "so"] singers = {Jagger: "Rock", Elvis: "Roll"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: "Max" age: 11 sister: name: "Ida" age: 9
var bitlist, kids, singers, song; song = ["do", "re", "mi", "fa", "so"]; singers = { Jagger: "Rock", Elvis: "Roll" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: "Max", age: 11 }, sister: { name: "Ida", age: 9 } };
Em JavaScript, você não pode usar palavras reservadas, como class, como propriedades de um objeto, sem envolvê-las com aspas como strings. CoffeeScript reconhece palavras reservadas usadas como chave (key) em um objeto e coloca aspas nelas para você, então você não precisa se preocupar com isso (por exemplo, quando usando jQuery).
$('.account').attr class: 'active' log object.class
$('.account').attr({ "class": 'active' }); log(object["class"]);
Escopo Léxico e Segurança de Variáveis O compilador CoffeeScript tem o cuidado de se certificar que todas as suas variáveis estão propriamente declaradas dentro de um escopo léxico — você mesmo nunca precisa escrever var.
outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers()
var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers();
Note como todas as declarações de variável foram colocadas no começo do escopo mais próximo, a primeira vez que elas aparecem. outer não está declarada dentro da função, porque ela já está no escopo; inner dentro da função, por outro lado, não deve ser capaz de mudar o valor da variável externa de mesmo nome, e portanto tem uma própria declaração.
Este comportamento é efetivamente idêntico ao escopo de Ruby para variáveis locais. Pelo fato de você não ter acesso direto à palavra-chave var, é impossível esconder uma variável externa de propósito, você deve apenas se referir a ela. Então tenha cuidado com o reuso de um nome de variável externa acidentalmente, principalmente se você estiver escrevendo uma função profundamente aninhada.
Embora suprimida nesta documentação para maior clareza, toda saída CoffeeScript é empacotada em uma função anônima: (function(){ ... })(); Este empacotador seguro, combinado com a geração automática da palavra-chave var, faz com que seja extremamente difícil de poluir os espaços de nomes (namespaces) globais por acidente.
Se você quiser criar variáveis de nível superior para outros scripts usarem, anexe-as como propriedades em window, ou no objeto exports em CommonJS. O operador existencial (mostrado abaixo), fornece a você uma forma confiável de descobrir onde adicioná-las; se você quiser as duas coisas (CommonJS e o navegador): exports ? this
If, Else, Unless, e Atribuição Condicional Declarações If/else podem ser escritas sem o uso de parênteses e chaves. Assim como funções e outras expressões de bloco, condicionais multi-linha são delimitados por indentação. Também existe uma forma pós-fixa, com o if ou unless ao final.
CoffeeScript pode compilar declarações if para expressões JavaScript, usando o operador ternário quando possível, e blocos de chaves caso contrário. Não existe declaração ternária explícita em CoffeeScript — você simplesmente usa uma declaração if normal em uma mesma linha.
mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill
var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill;
Splats... O objeto de argumentos de JavaScript é uma maneira útil de trabalhar com funções que aceitam um número variado de argumentos. CoffeeScript fornece splats ..., tanto para definições de função quanto para invocações, fazendo com que o número variável de argumentos seja um pouco mais saboroso.
gold = silver = rest = "unknown" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ "Michael Phelps" "Liu Xiang" "Yao Ming" "Allyson Felix" "Shawn Johnson" "Roman Sebrle" "Guo Jingjing" "Tyson Gay" "Asafa Powell" "Usain Bolt" ] awardMedals contenders... alert "Gold: " + gold alert "Silver: " + silver alert "The Field: " + rest
var awardMedals, contenders, gold, rest, silver, __slice = [].slice; gold = silver = rest = "unknown"; awardMedals = function() { var first, others, second; first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? __slice.call(arguments, 2) : []; gold = first; silver = second; return rest = others; }; contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"]; awardMedals.apply(null, contenders); alert("Gold: " + gold); alert("Silver: " + silver); alert("The Field: " + rest);
Laços e Compreensões de Listas A maioria dos laços (loops) que você escreverá em CoffeeScript serão compreensões de listas (list comprehensions) em arrays, objetos, e intervalos (ranges). Compreensões de listas substituem (e compilam para) laços for, com cláusulas guard opcionais e o valor atual do índice do array. Diferente de laços, as compreensões são expressões, e podem ser retornadas e atribuídas.
# Coma o almoço eat food for food in ['toast', 'cheese', 'wine'] # Jantar fino de cinco pratos courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu i + 1, dish for dish, i in courses # Refeição saudável foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate'
var courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref; _ref = ['toast', 'cheese', 'wine']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { food = _ref[_i]; eat(food); } courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; for (i = _j = 0, _len1 = courses.length; _j < _len1; i = ++_j) { dish = courses[i]; menu(i + 1, dish); } foods = ['broccoli', 'spinach', 'chocolate']; for (_k = 0, _len2 = foods.length; _k < _len2; _k++) { food = foods[_k]; if (food !== 'chocolate') { eat(food); } }
Compreensões devem ser capazes de lidar com a maioria dos casos onde você
de outra maneira usaria um laço normal, each/forEach, map,
ou select/filter, por exemplo:
shortNames = (name for name in list when name.length < 5)
Se você sabe o começa e termina o laço, ou gostaria de percorrer o laço
com incrementos de tamanho fixo, você pode usar um intervalo (range)
para especificar o começo e o fim das suas compreensões.
countdown = (num for num in [10..1])
var countdown, num; countdown = (function() { var _i, _results; _results = []; for (num = _i = 10; _i >= 1; num = --_i) { _results.push(num); } return _results; })();
Peceba que, pelo fato de estarmos atribuindo o valor das compreensões de lista (list comprehension) a uma variável no exemplo acima, CoffeeScript coleta o resultado de cada iteração em um array. Às vezes funções terminam com laços que servem apenas para rodar no contexto da própria função. Tenha cuidado para não retornar acidentalmente os resultados da compreensão, nestes casos apenas adicione um valor de retorno significativo — como true — ou null, ao final da sua função.
Para percorrer uma compreensão de intervalo em passos de tamanho fixo,
use by, por exemplo:
pares = (x for x in [0..10] by 2)
Compreensões também podem ser usadas para iterar sobre as chaves (key) e valores (value) em um objeto. Use of para sinalizar a compreensão sobre as propriedades de um objeto, em vez dos valores em um array.
yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld "#{child} is #{age}"
var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var _results; _results = []; for (child in yearsOld) { age = yearsOld[child]; _results.push("" + child + " is " + age); } return _results; })();
Se desejar iterar somente sobre as chaves (keys) que são
definidas no próprio objeto adicione uma verificação hasOwnProperty
,para evitar propriedades que possam ter sido herdadas do protótipo use
for own key, value of object
O único laço de baixo nível que CoffeeScript fornece é o laço while. A principal diferença de JavaScript é que o laço while pode ser usado como uma expressão, retornando um array contendo o resultado de cada iteração atravéz do laço.
# Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Rima de berçário num = 6 lyrics = while num -= 1 "#{num} little monkeys, jumping on the bed. One fell out and bumped his head."
var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } num = 6; lyrics = (function() { var _results; _results = []; while (num -= 1) { _results.push("" + num + " little monkeys, jumping on the bed. One fell out and bumped his head."); } return _results; })();
Para legibilidade, a palavra-chave until é equivalente a while not, e a palavra-chave loop é equivalente a while true.
Quando usando um laço JavaScript para gerar funções, é comum inserir um invólucro (wrapper) a fim de garantir que as variáveis do laço estejam corretamente fechadas, e todas as funções geradas não compartilhem apenas os valores finais. CoffeeScript fornece a palavra-chave do, que invoca imediatamente uma função passada com seus respectivos argumentos.
for filename in list do (filename) -> fs.readFile filename, (err, contents) -> compile filename, contents.toString()
var filename, _fn, _i, _len; _fn = function(filename) { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); }; for (_i = 0, _len = list.length; _i < _len; _i++) { filename = list[_i]; _fn(filename); }
Fatiamento e Substituição com Intervalos de Arrays Intervalos (ranges) também podem ser usados para extrair fatias (slices) de arrays. Com dois pontos (3..6), o intervalo é inclusivo (3, 4, 5, 6); Com trêz pontos (3...6), o intervalo exclui o final (3, 4, 5). Índices de fatias têm padrões úteis. Se o primeiro índice for omitido, terá o mesmo efeito que ter sido setado com 0, e se o segundo índice for omitido, terá o mesmo efeito que ter sido setado com o tamanho do array.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] start = numbers[0..2] middle = numbers[3...6] end = numbers[6..] copy = numbers[..]
var copy, end, middle, numbers, start; numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; start = numbers.slice(0, 3); middle = numbers.slice(3, 6); end = numbers.slice(6); copy = numbers.slice(0);
A mesma sintaxe pode ser usada com atribuição para substituir um segmento de um array com novos valores, "emendando-o" (splice).
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] numbers[3..6] = [-3, -4, -5, -6]
var numbers, _ref; numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; [].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;
Perceba que strings JavaScript são imutáveis, e não podem ser "emendadas".
Tudo é uma Expressão (pelo menos, o tanto quanto possível) Você deve ter notado que apesar de não termos adicionado declarações de retorno às funções CoffeeScript, mesmo assim elas retornam seu valor final. O compilador CoffeeScript tenta se assegurar que todas as declarações na linguagem possam ser usadas como expressões. Veja como o return acaba indo parar no final de cada ramo possível de execução na função abaixo.
grade = (student) -> if student.excellentWork "A+" else if student.okayStuff if student.triedHard then "B" else "B-" else "C" eldest = if 24 > 21 then "Liz" else "Ike"
var eldest, grade; grade = function(student) { if (student.excellentWork) { return "A+"; } else if (student.okayStuff) { if (student.triedHard) { return "B"; } else { return "B-"; } } else { return "C"; } }; eldest = 24 > 21 ? "Liz" : "Ike";
Apesar de funções sempre retornarem seu valor final, é possível e encorajado retornar o mais depressa possível de um corpo de função escrevendo explicitamente return (return value).
Pelo fato das declarações de variável ocorrerem no topo do escopo, pode ser usado atribuição dentro de expressões, até mesmo para variáveis que não foram vistas antes:
six = (one = 1) + (two = 2) + (three = 3)
var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3);
Coisas que poderiam, de outra maneira, ser declarações em JavaScript quando usadas como uma parte de uma expressão em CoffeeScript, são convertidas em expressões agrupando-as em um bloco. Isto permite a você fazer coisas úteis, como atribuir o resultado de uma compreensão de lista a uma variável:
# The first ten global properties. globals = (name for name of window)[0...10]
var globals, name; globals = ((function() { var _results; _results = []; for (name in window) { _results.push(name); } return _results; })()).slice(0, 10);
Bem como coisas bobas, como passar uma declaração try/catch diretamente em uma chamada de função:
alert( try nonexistent / undefined catch error "And the error is ... #{error}" )
alert((function() { try { return nonexistent / void 0; } catch (error) { return "And the error is ... " + error; } })());
Há um punhado de instruções em JavaScript que não podem ser verdadeiramente convertidas em expressões, como break, continue, e return. Se você faz uso delas dentro de um bloco de código, CoffeeScript não tentará realizar a conversão.
Operadores e Aliases Pelo fato de o operador == frequentemente causar coerção indesejável, é intransitivo, e tem um significado diferente do que em outras linguagens, CoffeeScript compila == para ===, e != para !==. Além disso, is compila para ===, e isnt para !==.
Você pode usar not como um apelido (alias) para !.
Por lógica, and compila para &&, e or para ||.
Em vez de uma nova linha ou ponto-e-vígula, then pode ser usado para separar condições de expressões, em instuções while, if/else, e switch/when.
Como em YAML, on e yes são o mesmo booleano true, enquanto off e no são o booleano false.
unless pode ser usado como o inverso de if.
Como um atalho para this.propriedade, você pode usar @propriedade.
Você pode usar in para testar a presença em array, e of para testar a presença de chave (key) de objeto JavaScript.
Tudo junto agora:
CoffeeScript | JavaScript |
---|---|
is | === |
isnt | !== |
not | ! |
and | && |
or | || |
true, yes, on | true |
false, no, off | false |
@, this | this |
of | in |
in | sem equivalente JS |
launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect "My name is #{@name}"
var volume, winner; if (ignition === true) { launch(); } if (band !== SpinalTap) { volume = 10; } if (answer !== false) { letTheWildRumpusBegin(); } if (car.speed < limit) { accelerate(); } if (pick === 47 || pick === 92 || pick === 13) { winner = true; } print(inspect("My name is " + this.name));
O Operador Existencial É um pouco difícil de verificar a existência de uma variável em JavaScript. if (variavel) ... chega perto, mais falha para zero (0), string vazia ("") e falso (false). O operador existencial de CoffeeScript ? retorna verdadeiro a menos que a variável seja null ou undefined, o que a faz análoga ao nil? de Ruby.
Ele também pode ser usado para atribuição condicional com mais segurança que ||= fornece, para casos onde você tenha que lidar com números ou strings.
solipsism = true if mind? and not world? speed = 0 speed ?= 15 footprints = yeti ? "bear"
var footprints, solipsism, speed; if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) { solipsism = true; } speed = 0; if (speed == null) { speed = 15; } footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
A variante do operador existencial ?. pode ser usada para absorver referências nulas em uma cadeia de propriedades. Use-o no lugar do operador . nos casos onde o valor base pode ser null ou undefined. Se todas a propriedades existem então você terá o resultado esperado, se a cadeia estiver quebrada, undefined é retornado em vez de TypeError que seria o normal.
zip = lottery.drawWinner?().address?.zipcode
var zip, _ref; zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;
Absorver valores nulos (null) é similar ao andand gem de Ruby, e ao safe navigation operator em Groovy.
Classes, Herança, and Superclasses A herança prototipada de JavaScript sempre foi um pouco confusa, com toda uma árvore genealógica de bibliotecas que fornecem uma sintaxe mais clara para herança clássica no topo dos protótipos JavaScript: Base2, Prototype.js, JS.Class, etc. As bibliotecas oferecem um "açúcar sintático" (syntatic sugar), e a herança padrão seria completamente utilizável se não fosse por umas pequenas exceções: é estranho chamar a superclasse (a implementação do protótipo do objeto da função atual), e é estranho utilizar a cadeia de protótipo corretamente.
Em vez de anexar funções a um protótipo repetidamente, CoffeeScript fornece uma estrutura básica class que permite a você nomear sua classe, setar a superclasse, atribuir propriedades de protótipo, e definir o construtor em uma única expressão atribuível.
Funções construtoras são nomeadas, para melhor apoiar os rastreamentos úteis de pilha (stack trace. Na primeira classe no exemplo abaixo, this.constructor.name is "Animal".
class Animal constructor: (@name) -> move: (meters) -> alert @name + " moved #{meters}m." class Snake extends Animal move: -> alert "Slithering..." super 5 class Horse extends Animal move: -> alert "Galloping..." super 45 sam = new Snake "Sammy the Python" tom = new Horse "Tommy the Palomino" sam.move() tom.move()
var Animal, Horse, Snake, sam, tom, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Animal = (function() { function Animal(name) { this.name = name; } Animal.prototype.move = function(meters) { return alert(this.name + (" moved " + meters + "m.")); }; return Animal; })(); Snake = (function(_super) { __extends(Snake, _super); function Snake() { return Snake.__super__.constructor.apply(this, arguments); } Snake.prototype.move = function() { alert("Slithering..."); return Snake.__super__.move.call(this, 5); }; return Snake; })(Animal); Horse = (function(_super) { __extends(Horse, _super); function Horse() { return Horse.__super__.constructor.apply(this, arguments); } Horse.prototype.move = function() { alert("Galloping..."); return Horse.__super__.move.call(this, 45); }; return Horse; })(Animal); sam = new Snake("Sammy the Python"); tom = new Horse("Tommy the Palomino"); sam.move(); tom.move();
Se estruturar seus protótipos da maneira clássica não é sua praia, CoffeeScript fornece umas conveniências de baixo nível. O operador extends ajuda com a configuração de protótipo adequada, e pode ser usado para criar uma cadeia de herança entre qualquer par de funções construtoras; :: lhe dá acesso rápido a uma propriedade de objeto; e super() é convertido em uma chamada direta ao método com o mesmo nome do seu ancestral (superclasse).
String::dasherize = -> this.replace /_/g, "-"
String.prototype.dasherize = function() { return this.replace(/_/g, "-"); };
Finalmente, definições de classe são blocos de código executável, o que faz com
que as possibilidades de metaprogramação se tornem interessantes. Por causa do
contexto de uma definição de classe, this é o próprio objeto de classe
(a função construtora), você pode atribuir propriedades estáticas usando
@property: value, e chamar funções definidas em classes pai:
@attr 'title', type: 'text'.
Atribuição de Troca Para fazer com que a extração de valores de arrays e objetos complexos mais conveniente, CoffeeScript implementa a sintaxe destructuring assignment proposta pelo ECMAScript Harmony. Quando você atribui um array ou objeto para um valor, CoffeeScript se fragmenta e combina os dois lados, atribuindo os valores da direita às variáveis da esquerda. De maneira mais simples, pode ser usado para atribuição paralela:
theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait]
var theBait, theSwitch, _ref; theBait = 1000; theSwitch = 0; _ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
Mas também é bastante útil para lidar com funções que retornam multiplos valores.
weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, "Mostly Sunny"] [city, temp, forecast] = weatherReport "Berkeley, CA"
var city, forecast, temp, weatherReport, _ref; weatherReport = function(location) { return [location, 72, "Mostly Sunny"]; }; _ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast = _ref[2];
Atribuição de troca (Destructuring assignment) pode ser usada com qualquer profundidade de array ou aninhamento de objeto, para ajudar a extrair propriedades profundamente aninhadas.
futurists = sculptor: "Umberto Boccioni" painter: "Vladimir Burliuk" poet: name: "F.T. Marinetti" address: [ "Via Roma 42R" "Bellagio, Italy 22021" ] {poet: {name, address: [street, city]}} = futurists
var city, futurists, name, street, _ref, _ref1; futurists = { sculptor: "Umberto Boccioni", painter: "Vladimir Burliuk", poet: { name: "F.T. Marinetti", address: ["Via Roma 42R", "Bellagio, Italy 22021"] } }; _ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[0], city = _ref1[1]);
Atribuição de troca pode até ser combinada com splats.
tag = "<impossible>" [open, contents..., close] = tag.split("")
var close, contents, open, tag, _i, _ref, __slice = [].slice; tag = "<impossible>"; _ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];
Vinculação de Funções Em JavaScript, a palavra-chave this é dinamicamente "escopada" para que o objeto seja referente a função da qual ele está vinculado. Se você passar uma função como um callback ou vinculá-la a um objeto diferente, o valor original de this será perdido. Se você não está familiarizado com este comportamento, este artigo fornece uma boa visão dessas peculiaridades.
A seta dupla => pode ser usada tanto para definir uma função quanto para vinculá-la ao valor atual de this no lugar certo. Isto é útil quando usamos bibliotecas baseadas em callbacks como Prototype ou jQuery, para criar funções iteradoras para passar para each, ou para funções manipuladoras de eventos usarem com bind. Funções criadas com a seta dupla são capazes de acessar propriedades do this onde elas são definidas.
Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').bind 'click', (event) => @customer.purchase @cart
var Account; Account = function(customer, cart) { var _this = this; this.customer = customer; this.cart = cart; return $('.shopping_cart').bind('click', function(event) { return _this.customer.purchase(_this.cart); }); };
Se tivéssemos usado -> no callback acima, @customer teria se referido à propriedade "customer" indefinida do elemento DOM, e tentado chamar purchase() nela teria gerado uma exceção.
Quando usados em uma definição de classe, métodos declarados com a seta dupla serão automaticamente vinculados a cada instância da classe quando a instância for construída.
JavaScript Embutido Provavelmente, você nunca precisará utilizar isso, mas se você precisar intercalar fragmentos de JavaScript dentro do seu CoffeeScript, pode utilizar crases para incluí-los diretamente.
hi = `function() { return [document.title, "Hello JavaScript"].join(": "); }`
var hi; hi = function() { return [document.title, "Hello JavaScript"].join(": "); };
Switch/When/Else Instruções switch em JavaScript são um pouco inconvenientes. Você se lembrar de incluir um break ao final de toda instrução case para evitar de cair no case padrão (default) acidentalmente. CoffeeScript impede essa caída acidental, e pode converter o switch em expressões retornáveis e atribuíveis. O formato é: codição switch, cláusulas when e cláusulas else como o case padrão.
Como em Ruby, instruções switch em CoffeeScript podem ter multiplos valores para cada cláusula when. Se qualquer um dos valores casar, a cláusula é executada.
switch day when "Mon" then go work when "Tue" then go relax when "Thu" then go iceFishing when "Fri", "Sat" if day is bingoDay go bingo go dancing when "Sun" then go church else go work
switch (day) { case "Mon": go(work); break; case "Tue": go(relax); break; case "Thu": go(iceFishing); break; case "Fri": case "Sat": if (day === bingoDay) { go(bingo); go(dancing); } break; case "Sun": go(church); break; default: go(work); }
Try/Catch/Finally Instruções try/catch são as mesmas do JavaScript (contudo, funcionam como expressões).
try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp()
try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error) { print(error); } finally { cleanUp(); }
Comparações em Cadeia CoffeeScript pega emprestado as comparações em cadeia (em inglês) de Python — facilitando testar se um valor está dentro de um determinado intervalo.
cholesterol = 127 healthy = 200 > cholesterol > 60
var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60);
Interpolação de String, Blocos de String e Blocos de Comentário A interpolação de string no estilo Ruby está incluída no CoffeeScript. Strings de aspas duplas permitem valores interpolados usando #{ ... }, e aspas simples são apenas strings literais.
author = "Wittgenstein" quote = "A picture is a fact. -- #{ author }" sentence = "#{ 22 / 7 } is a decent approximation of π"
var author, quote, sentence; author = "Wittgenstein"; quote = "A picture is a fact. -- " + author; sentence = "" + (22 / 7) + " is a decent approximation of π";
Strings multi-linha são permitidas em CoffeeScript.
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world..."
var mobyDick; mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
Blocos de strings podem ser usadas para armazenar texto formatado ou indentado (ou, se você apenas não gosta de escapar aspas e apóstrofos). O nível de indentação que começa o bloco é mantido do começo ao fim, então você pode manter tudo alinhado com o corpo do seu código.
html = """ <strong> cup of coffeescript </strong> """
var html; html = "<strong>\n cup of coffeescript\n</strong>";
Blocos de strings de aspas duplas, assim como qualquer string de aspas duplas, também permitem interpolação.
Às vezes você pode querer passar um bloco de comentário para o JavaScript gerado. Por exemplo, quando você precisa embutir um cabeçalho de licenciamento no topo de um arquivo. Comentários em bloco, que refletem a sintaxe de strings em bloco, são preservados no código gerado.
### CoffeeScript Compiler v1.3.3 Released under the MIT License ###
/* CoffeeScript Compiler v1.3.3 Released under the MIT License */
Blocos de Expressões Regulares De forma similar aos blocos de strings e comentários, CoffeeScript também suporta blocos de expressões regulares (regexes) — expressões regulares extendidas que ignoram espaços em branco internos e que podem conter comentários e interpolação. Modelado de forma similiar ao modificador /x de Perl, os blocos de expressão regular do CoffeeScript são delimitados por /// e fazem com que as expressões regulares se tornem legíveis. Veja o exemplo abaixo:
OPERATOR = /// ^ ( ?: [-=]> # function | [-+*/%<>&|^!?=]= # compound assign / compare | >>>=? # zero-fill right shift | ([-+:])\1 # doubles | ([&|<>])\2=? # logic / shift | \?\. # soak access | \.{2,3} # range or splat ) ///
var OPERATOR; OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
CoffeeScript inclui um sistema de construção (build system) muito simples parecido com o Make e o Rake. Naturalmente, ele é chamado de Cake, e é usado pelas tarefas que constroem e testam a própria linguagem CoffeeScript. Tarefas (tasks) são definidas em um arquivo chamado de Cakefile, e podem ser invocadas chamando cake [tarefa] de dentro do diretório. Para imprimir uma lista de todas as tarefas e opções, basta digitar cake.
Definições de tarefas são escritas em CoffeeScript, assim você pode incluir código arbitrário em seu Cakefile. Defina uma tarefa com um nome, uma descrição, e a função que será invocada quando a tafera for executada. Se sua tarefa tem uma opção de linha de comando, você pode definir a opção com flags curtos e longos, e ela ficará disponível on objeto options. Abaixo há uma tarefa que usa a API Node.js para reconstruir o analizador sintático do CoffeeScript:
fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile "#{dir}/parser.js", code
var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile("" + dir + "/parser.js", code); });
Se você precisa executar uma tarefa antes de outra — por exemplo, rodando build antes de test, você pode utilizar a função invoke: invoke 'build'. Tarefas cake são uma maneira minimalista de expor suas funções CoffeeScript na linha de comando, então não nada muito extravagante. Se você precisa de dependências, ou de callbacks assíncronos, é melhor você mesmo colocá-los em seu código — e não a tarefa cake.
Mesmo não sendo recomendável para uso em produção, códigos CoffeeScript podem ser incluídos diretamente no navegador usando tags <script type="text/coffeescript">. O código fonte inclui uma versão compactada e minificada do compilador (Faça o download da versão atual, 39k em gzip) como em extras/coffee-script.js. Inclua este arquivo na página com as tags inline do CoffeeScript, e ele irá compilar e validar os scripts – nesta ordem.
Na verdade, o pequeno script que executa "Experimente CoffeeScript" acima, assim como o jQuery do menu, é implementado exatamente dessa maneira. Abra o código fonte e olhe para o final da página para ver o exemplo. Incluir o script também lhe dá acesso ao CoffeeScript.compile() assim você pode abrir o Firebug – ou o Inspector no Chrome – e tentar compilar algumas strings.
As advertências comuns sobre a aplicação de CoffeeScript — seus scripts inline serão executados dentro de um ambiente separado, então se você quiser expor variáveis ou funções globais, vincule-as ao objeto window.
Existem vários meios excelentes para ajudá-lo a começar com CoffeeScript, alguns deles estão disponíveis online gratuitamente.
A melhor lista de exemplos CoffeeScript open-source pode ser encontrada no GitHub. Mais alguns:
Ajuda rápida e conselhos podem ser encontrados no canal de IRC CoffeeScript. Entre em #coffeescript em irc.freenode.net, ou clique no botão abaixo para abrir uma sessão webchat nesta página.
1.1.2 Correção na formatação de comentários de bloco, compilação de ?=, chamadas implícitas contra estruturas de controle, invocação implícita de um bloco try/catch, argumentos variádicos vazando para o escopo local, número de linha de erro de sintaxe seguido de heregex, acesso a propriedade em números literais entre parênteses, vincula métodos de classes e super com nomes reservados, reformulação do REPL, ponto-e-vírgula consecutivos compilados, comentários em bloco de objetos chamados de forma implícita e um bug no Chrome.
1.1.1
Correção de bug em classes com funções construtoras externas, ver Issue #1182.1.1.0
Quando executado pelo coffee, process.argv e similares agora informam coffee ao invés de node. Melhor compatibilidade com módulos no Node.js 0.4.x. A saída do REPL é agora colorida, como no Node.js. Obrigatório dar um nome aos CoffeeScripts concatenados quando usada a flag --join. Correção na análise léxica de divisão composta =/ como regex. Todas as tags text/coffeescript agora devem ser executadas na ordem que são incluídas. Corrigido um problema ao estender subclasses usando funções construtoras externas. Corrigido problema de velocidade exponencial com chamadas de funções em cadeias muito grandes. Globais não vazam mais no REPL CoffeeScript. Parâmetros splatted são declarados localmente para a função.1.0.1
Corrigido bug no analizador léxico com identificadores Unicode. REPL atualizado para compatibilidade com Node.js 0.3.7. Corrigido bug na requisição de caminhos relativos no REPL. return e return undefined finais agora são otimizados. O módulo util agora não é mais usado devido a compatibilidade com Node.js 0.2.5. Corrigido um caso onde um return condicional poderia disparar o case padrão. Otimização de objetos vazios na atribuição de desestruturação.1.0.0
Laços (loops) CoffeeScript não tentam mais preservar o escopo do bloco quando funções estão sendo geradas dentro do corpo do laço. Caso necessário, você pode usar a palavra-chave do para criar um wrapper de maneira fácil. Adicionada a flag --nodejs para passar opções diretamente ao executável node. Melhor comportamento no uso de declarações dentro de expressões. Corrigido slicing inclusivo através de -1, para todos os navegadores, e splicing com expressões como pontos de parada.0.9.6
REPL agora formata de forma correta stacktraces, e continua rodando entre exceções assíncronas. Usando --watch agora imprime timestamps quandos os arquivos são compilados. Corrigido bug que deixava variáveis vazar dentro de plucked closures-loops. Construtores agora mantêm o seu local de declaração dentro do corpo da classe. Chaves de objetos dinâmicos foram removidas. Classes aninhadas agora são suportadas. Corrige contexto de execução para funções splats nuas (naked splatted functions). Correção de bug para inversão de comparação em cadeia. Instanciação de classes em cadeia agora funcionam de forma correta com splats.
0.9.5
Coco.
Heregexes (regexes estendidas) foram adicionadas.
Funções agora podem ter valores padrão em seus argumentos.
Corpo das classes agora são código executável.
Melhorias nos erros de sintaxe para CoffeeScript inválido.
nudefined agora funciona como null, e não pode ser atribuído
a um novo valor.
Houveram mudanças nas regras de precedência em relação a comprehensions single-line:
result = i for i in list
era analisado (parsed) em result = (i for i in list)
por padrão ... agora é analisado (parsed) em
(result = i) for i in list.
0.9.4
CoffeeScript agora usa melhores nomes de variáveis temporárias, e recicla suas referências depois do uso. Adicionado suporte a require.extensions para o Node.js 0.3. Carregar CoffeeScript no navegador agora adiciona apenas um objeto CoffeeScript no escopo global. Correções de bug em objetos implícitos e comentários em bloco em alguns casos extremos.0.9.3
Switch agora compila para switch nativo de JavaScript — eles antigamente compilavam para if/else encadeados para compatibilidade com a versão 1.3 do JavaScript. Absorver a invocação de uma função agora é suportado. Usuários do editor RubyMine agora podem utilizar a flag --watch.0.9.2
Especificar o começo e fim de um range literal agora é opcional, ex. array[3..]. Agora é possível usar a not instance of. Importante correção de bug com indentação aninhada significante e não-significante (Issue #637). Adicionado a flag --require que permite que você ligue com o comando coffee. Adicionado um arquivo jsl.conf customizado para a sua instalação preferida de JavaScriptLint. Maior velocidade no tempo de compilação da gramática Jison. Comentários em bloco agora podem ser usados com uma sintaxe amigável a minifiers JavaScript. Adicionados operadores de atribuição compostos bitwise. Correção de bugs nos objetos literais implícitos com chaves iniciadas em números e string, como o sujeito de chamadas implícitas, e como parte de atribuições compostas.0.9.1
Correções de bug para 0.9.1. Melhora a manipulação de objetos implícitos mistos, chamadas implícitas a funções, e identação implícita. Interpolação de strings e regex agora é feita apenas com #{ ... }, como em Ruby.0.9.0
As série de versões 0.9 são candidatas para o lançamento da versão 1.0. A versão 0.9 introduz várias mudanças que quebram a compatibilidade com versões anteriores: atribuições agora usam =, e objetos literais usam :, como em JavaScript. Isto permite termos objetos literais implícitos, e definições de objetos no estilo YAML. Meia atribuições (half assignments) foram removidas, devido a +=, or=, e outros. Interpolação agora usa # ao invés de $ — pois o sinal de dólar pode fazer parte de um indentificador JS válido. Range comprehensions ao contrário são seguras novamente, e otimizadas para laços for quando criadas com números inteiros como final do laço. Um forma sem proteção e rápida de object comprehension foi adicionada: for all key, value of object. O uso da palavra-chave super sem argumentos agora redireciona todos os argumentos passados a função, como em Ruby. Se você estender (extends) a classe B da classe pai A, e se A possui um método extended definido, ele irá ser chamado, passando B — isto habilita herança estática, entre outras coisas. Saída mais limpa para bound functions com =>. @variables agora podem ser usadas nas listas de parâmetros, com o parâmetro sendo automaticamente setado como uma propriedade do objeto — útil em construtores e setter functions. Contrutores agora podem receber splats.0.7.2
Rápida correção de bug (logo depois da 0.7.1) de um problema que impedia que algumas opções da linha de comando coffee fossem tratadas de forma correta em algumas circunstâncias.0.7.1
Comentários no estilo bloco agora são passados e imprimidos como comentários em bloco JavaScript -- fazendo deles úteis para licenças e cabeçalhos de direitos legais (copyright). Melhor suporte na execução de scripts coffee via hashbangs. Melhoria nos erros de sintaxe para tokens que não estão na gramática.0.7.0
O estilo oficial de variáveis no CoffeeScript agora é camelCase, assim como em JavaScript. Palavras reservadas agora podem ser chaves de objetos, e serão automaticamente postas entre aspas para você. Comprehensions de range agora geram um código mais limpo, mas você tem de especificar by -1 se deseja iterar ao contrário. Relatório de erros de sintaxe foram bastante melhorados desde a última versão. Executando coffee sem argumentos agora chama o REPL, com suporte a Readline. O operador de bind <- foi removido do CoffeeScript. A palavra-chave loop foi adicionada, o que é equivalente ao laço while true. Comprehensions que possuem closures agora vão fechar sobre suas variáveis, como na semântica de um forEach. Agora é possível usar bound functions nas definições de classes. Por consistência, a in b é agora uma checagem de presença no array, e a of b é uma checagem de chave no objeto. Comentários não são mais passados para o JavaScript gerado.0.6.2
O comando coffee agora preserva a estrutura de pastas quando compila um diretório cheio de scripts. Corrigido duas omissões que impediam o compilador CoffeeScript de rodar dentro do Internet Explorer. Existe agora uma sintaxe para comentários em bloco, similar a sintaxe já existente para heredocs. Pattern matching ao estilo ECMA Harmony DRY (Don't Repeat Yourself) é agora suportado, onde o nome da propriedade é o mesmo nome do valor: {name, length}: func. Pattern matching agora é permitido dentro de variáveis comprehension. unless é agora suportado como um bloco. Laços until foram adicionados, como o inverso dos laços while. Declarações switch agora são permitidas sem o objeto de cláusulas. Compatível com Node.js v.0.1.95.0.6.1
Atualização do CoffeeScript para compatibilidade com o novo Node.js v0.1.900.6.0
Vírgulas no fim das linhas agora são permitidas, a-la Python. Propriedades estáticas agora podem ser atribuídas dentro das definições de classes, usando a notação @propriedade.0.5.6
Interpolação agora pode ser usada dentro de expressões regulares and heredocs, assim como em strings. Adicionado o operador <- para binding. Atribuição de meia-expressões agora são permitidas ao invés do ||=. O objeto arguments não é mais convertido automaticamente em array. Após o require, Node.js pode diretamente carregar arquivos .coffee, graças a registerExtension. Splats múltiplos agora podem ser usados nas chamadas de funções, arrays e em combinação de padrões (pattern matching).0.5.5 Stan Angeloff. Uma vez que --run está ativo por padrão desde a versão 0.5.3, atualiza --stdio e --eval para também rodarem por padrão, passe a flag compile se quiser também imprimir o resultado.
Interpolação de strings, contribuído por0.5.4
Correção de bug que corrige as constantes globais __filename e __dirname do Node.js. Pequenas alterações para uma análise sintática mais flexível de funções aninhadas e comentários mal indentados. Atualizações para a última API do Node.js.0.5.3
CoffeeScript agora tem uma sintaxe para definição de classes. Muitos dos componentes do core (Node, Lexer, Rewriter, Scope, Optparse) estão a usando. Cakefiles podem usar optparse.coffee para definir opções para tasks. --run agora é a flag padrão para o comando coffee, use --compile para salvar JavaScripts. Correção de bug em uma ambiguidade entre RegExp literais e divisões encadeadas.
0.5.2
extras/coffee-script.js. Ele irá automaticamente
rodar qualquer tag de script do tipo text/coffeescript.
Adiciona a opção --stdio ao comando coffee, para uso
com o pipe.
0.5.1
Melhorias na absorção de referências nulas (null soaking) com o operador existencial, incluindo a absorção em propriedades indexadas. Adicionado condições aos laços while, o que permite agora usá-los como filtros com when, da mesma forma que comprehensions.0.5.0
A versão 0.5.0 do CoffeScript é um grande lançamento (major release). Ao mesmo tempo que não existe mudanças na linguagem, o compilador Ruby foi removido em troca de um compilador escrito em CoffeeScript.
0.3.2
Node.js agora é o engine padrão. Caso queira continuar a usar
a antiga engine, Narwhal, passe a flag --narwhal.
0.3.0
O símbolo para função foi modificado para ->, e o símbolo para
bound function agora é =>.
Listas de parâmetros nas definições de funções agora devem estar entre
parênteses.
Adicionado property soaking, com o operador ?..
Parênteses agora são opcionais quando funções com argumentos são invocadas.
Removida a sintaxe obsoleta de bloco literal.
0.2.6
Adicionado comparações em cadeia como em Python, o operador de existência ?=, e alguns exemplos do Beautiful Code. Correções de bugs relacionados a conversão de declarações para expressões, conversão de argumentos para array, e o syntax highlighter para TextMate.0.2.5
As condições dos switchs agora aceitam vários valores ao mesmo tempo — Se algum deles for verdadeiro, o case irá rodar. Adicionado a senta longa ==>, que define e imediatamente vincula (bind) uma função ao this. Laços while agora podem ser usados como expressões, do mesmo modo como comprehensions podem. Splats podem ser usadas dentro de padrões de combinação para capturar o resto de um array.0.2.4
Adicionada a atribuição de desestruturação seguindo a proposta do ECMAScript Harmony, para tratar da extração de valores de arrays e objetos aninhados. Adicionado heredocs sensíveis a indentação (indentation-sensitive) para uma melhor formatação de strings ou pedaços de código.0.2.3
Removida a palavra-chave ino, sendo substituída por of para object comprehensions. Agora elas funcionam da seguinte forma: for prop, value of object.0.2.2
Quando executar uma comprehension sobre um objeto, usar ino, ao invés de in, o que ajuda a gerar um código menor e mais eficiente durante a compilação. Adicionado :: como um atalho para .prototype. O símbolo para "splat" foi modificado de um asterisco * prefixado para reticências ... com sufixos. Adicionado o operador in de JavaScript, decalarações return vazias, laços while vazios. Funções contrutoras que iniciam com uma letra maiúscula agora incluem uma checagem de segurança para assegurar que a nova instância do objeto seja retornada. A palavra-chave extends agora funciona de forma idêntica a goog.inherits da Google Closure Library.0.2.1
Objetos passados como argumentos agora são convertidos em arrays reais quando referenciados.0.2.0 Liam O'Connor-Davis pela ajuda com espaço em branco e expressões.
Grande lançamento (major release). Espaço em branco significativo. Melhor conversão de declaração para expressão. Splats. Literais splice. Comprehensions de objetos. Blocos. Operador existencial. Muito obrigado a todos que postaram issues, com um agradecimento especial para0.1.6
Correção de bug para rodar coffee --interactive e --run fora do diretório CoffeeScript. Correção de bug para funções e if aninhados.0.1.5
Literais Array slice e array comprehensions podem ambos utilizar uma sintaxe no estilo Ruby para especificar o começo e fim de um range. Declaração de variáveis JavaScript agora são enviadas para o topo do escopo, fazendo com que todas as declarações de atribuição fiquem dentro de expressões. É possível usar \ para "escapar" (escape) novas linhas. O comando coffee-script agora é chamado coffee.0.1.4 C#. Devido a vários pedidos, agora é possível usar = para atribuição. Diferente de JavaScript, = pode também ser usado dentro de objetos literais, da mesma forma que :. Feita uma correção gramatical para chamadas de funções em cadeia (chain calls) como func(1)(2)(3)(4). Herança e a palavra-chave super não utilizam mais __proto__, fazendo com sejam compatíveis com o IE.
A extensão oficial do CoffeScript agora é .coffee ao contrário de .cs, que pertence a0.1.3
O comando coffee agora inclui a opção --interactive, que chama uma sessão inteterativa do CoffeeScript, e --run, que compila e executa um script. Ambas as opções dependem da instalação do Narwhal. A palavra-chave aint foi trocada por isnt, o que faz mais sentindo junto com is. Strings com aspas agora são permitidas como identificadores dentro de objetos literais: ex. {"5+5": 10}. Todos os operadores de atribuição agora usam dois pontos: +:, -:, *:, etc.0.1.2 Narwhal (como um pacote Tusk), contribuído por Tom Robinson, incluindo bin/cs como um REPL de CoffeeScript e interpretador. Nova opção --no-wrap para suprimir o wrapper da função de segurança.
Corrigido um bug quando super() era chamado por mais de um nível de herança, com a re-adição da palavra-chave extends. Adicionado suporte experimental a0.1.1
Adicionado instanceof e typeof como operadores.0.1.0
Primeira versão do CoffeeScript liberada.Traduzido para o português por Loop Infinito (@loopinfinito).