CoffeeScriptは、JavaScriptにコンパイルされる小さな言語です。ぎこちないJava風の外見の下に、JavaScriptは常に素晴らしい心臓を持っていました。CoffeeScriptは、JavaScriptの良い部分をシンプルに公開しようとする試みです。

CoffeeScriptの黄金律は、「それは単なるJavaScriptである」です。コードは1対1で同等のJSにコンパイルされ、ランタイムでの解釈はありません。既存のJavaScriptライブラリをCoffeeScriptからシームレスに使用できます(その逆も同様です)。コンパイルされた出力は可読性が高く、きれいにフォーマットされており、同等の自作JavaScriptと同等またはそれ以上の速度で実行される傾向があります。

CoffeeScriptコンパイラは、すべてのJavaScriptランタイムで実行される出力JavaScriptを生成するために最善を尽くしていますが、例外があります。ジェネレータ関数for…from、またはタグ付きテンプレートリテラルは、ターゲットランタイムがそれらをサポートできることを知っている場合にのみ使用してください。モジュールを使用する場合は、追加のツールを使用してそれらを解決する必要があります。

最新の1.xバージョン: 1.12.7

npm install -g coffeescript

CoffeeScript 2にアップグレードしましょう! ES2015クラスasync/awaitJSXオブジェクトのレスト/スプレッド構文、および最新の構文を使用して生成されたJavaScriptのサポートが追加されました。詳細はこちら

概要

左側にCoffeeScript、右側にコンパイルされたJavaScriptの出力が表示されます。

# Assignment:
number   = 42
opposite = true

# Conditions:
number = -42 if opposite

# Functions:
square = (x) -> x * x

# Arrays:
list = [1, 2, 3, 4, 5]

# Objects:
math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

# Splats:
race = (winner, runners...) ->
  print winner, runners

# Existence:
alert "I knew it!" if elvis?

# Array comprehensions:
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;
})();
実行: cubes

インストール

coffeeのコマンドラインバージョンは、Node.jsユーティリティとして利用できます。コアコンパイラはNodeに依存せず、任意のJavaScript環境またはブラウザで実行できます(CoffeeScriptを試すを参照)。

インストールするには、まず、最新安定版のNode.jsが動作していることを確認してください。npmを使用して、CoffeeScriptをグローバルにインストールできます。

npm install --global coffeescript

これにより、coffeeコマンドとcakeコマンドがグローバルに使用できるようになります。

プロジェクトの依存関係としてCoffeeScriptが必要な場合、そのプロジェクトのフォルダ内でローカルにインストールできます。

npm install --save coffeescript

coffeeコマンドとcakeコマンドは、まず現在のフォルダにCoffeeScriptがローカルにインストールされているかどうかを確認し、インストールされている場合はそのバージョンを使用します。これにより、CoffeeScriptの異なるバージョンをグローバルおよびローカルにインストールできます。

使用方法

インストール後、coffeeコマンドを使用できるようになります。このコマンドは、スクリプトを実行し、.coffeeファイルを.jsにコンパイルし、インタラクティブなREPLを提供します。coffeeコマンドは次のオプションを受け付けます。

オプション 説明
-c, --compile .coffeeスクリプトを、同じ名前の.js JavaScriptファイルにコンパイルします。
-m, --map コンパイルされたJavaScriptファイルと共にソースマップを生成します。JavaScriptにもsourceMappingURLディレクティブを追加します。
-M, --inline-map --mapと同様ですが、ソースマップは別のファイルではなく、コンパイルされたJavaScriptファイルに直接含まれます。
-i, --interactive 短いスニペットを試すためのインタラクティブなCoffeeScriptセッションを開始します。引数なしでcoffeeを呼び出すことと同じです。
-o, --output [DIR] コンパイルされたすべてのJavaScriptファイルを指定されたディレクトリに書き出します。--compileまたは--watchと組み合わせて使用します。
-w, --watch ファイルの変更を監視し、ファイルが更新されるたびに指定されたコマンドを再実行します。
-p, --print JavaScriptをファイルとして書き出す代わりに、stdoutに直接出力します。
-s, --stdio STDINにCoffeeScriptを入力し、STDOUTにJavaScriptを返します。他の言語で記述されたプロセスと連携する場合に適しています。例:
cat src/cake.coffee | coffee -sc
-l, --literate コードをリテラシーCoffeeScriptとして解析します。stdioを介してコードを直接渡す場合、または拡張子なしのファイル名を使用する場合にのみ、これを指定する必要があります。
-e, --eval コマンドラインから直接CoffeeScriptのスニペットをコンパイルして出力します。例:
coffee -e "console.log num for num in [10..1]"
-r, --require [MODULE] --evalフラグで与えられたコードを評価するか、REPLを開始する前に、指定されたモジュールをrequire()します。
-b, --bare 最上位の関数安全ラッパーなしでJavaScriptをコンパイルします。
-t, --tokens CoffeeScriptを解析する代わりに、字句解析を行い、トークンストリームを出力します。コンパイラのデバッグに使用されます。
-n, --nodes CoffeeScriptをコンパイルする代わりに、字句解析と構文解析を行い、構文木を出力します。コンパイラのデバッグに使用されます。
--nodejs node実行ファイルには、--debug--debug-brk--max-stack-size--expose-gcなどの便利なオプションを設定できます。このフラグを使用して、オプションをNode.jsに直接転送します。複数のフラグを渡すには、--nodejsを複数回使用します。
--no-header 「Generated by CoffeeScript」ヘッダーを抑制します。

リテラシーCoffeeScript

通常のプログラミング言語として使用される以外にも、CoffeeScriptは「リテラシー」モードで記述することもできます。ファイルを.litcoffee拡張子で名前付けると、Markdownドキュメントとして記述できます。これは、実行可能なCoffeeScriptコードでもあるドキュメントです。コンパイラは、インデントされたブロック(Markdownによるソースコードの表示方法)をコードとして扱い、残りの部分をコメントとして無視します。

ちょっとした遊びとして、コンパイラの少しの部分が現在この方法で実装されています。ドキュメントとしてraw、およびテキストエディタで適切に強調表示されています。

言語リファレンス

このリファレンスは、必要に応じて上から下まで読むことができるように構成されています。後のセクションでは、以前に紹介したアイデアと構文を使用しています。JavaScriptの知識があることを前提としています。次の例ではすべて、ソースCoffeeScriptが左側に、JavaScriptへの直接コンパイルが右側に表示されます。

多くの例は(意味をなす場合)、右側の実行ボタンを押して実行でき、左側の読み込みボタンを押して「CoffeeScriptを試す」コンソールに読み込むことができます。

まず、基本事項です。CoffeeScriptは、コードのブロックを区切るために重要な空白を使用します。式を終了するためにセミコロン;を使用する必要はありません。行を終了するだけで十分です(ただし、複数の式を1行に収めるためにセミコロンを使用することもできます)。関数if文switch、およびtry/catchでコードのブロックを囲むために中括弧{ }を使用する代わりに、インデントを使用します。

引数を渡す場合、関数を呼び出すために括弧を使用する必要はありません。暗黙の呼び出しは、行またはブロック式の終わりまで継続します。
console.log sys.inspect objectconsole.log(sys.inspect(object));

関数

関数は、オプションの括弧内のパラメータリスト、アロー、および関数本体によって定義されます。空の関数は次のようになります: ->

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;
};
読み込み
実行: cube(5)

関数には、引数にデフォルト値を設定することもできます。これは、入力引数が不足している場合(nullまたはundefined)に使用されます。

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 + "...";
};
読み込み
実行: fill("cup")

オブジェクトと配列

オブジェクトと配列のCoffeeScriptリテラルは、JavaScriptの同等物と非常によく似ています。各プロパティがそれぞれ独自の行にリストされている場合、コンマは省略可能です。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
  }
};
読み込み
実行: song.join(" … ")

JavaScriptでは、classなどの予約語を、文字列として引用せずにオブジェクトのプロパティとして使用することはできません。CoffeeScriptは、オブジェクトのキーとして使用される予約語を認識し、自動的に引用するため、心配する必要はありません(たとえば、jQueryを使用する場合)。

$('.account').attr class: 'active'

log object.class
$('.account').attr({
  "class": 'active'
});

log(object["class"]);
読み込み

同じ名前の変数を使用してキーを設定する場合、CoffeeScriptにはオブジェクトを作成するためのショートカットがあります。

name = "Michelangelo"
mask = "orange"
weapon = "nunchuks"
turtle = {name, mask, weapon}
output = "#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!"
var mask, name, output, turtle, weapon;

name = "Michelangelo";

mask = "orange";

weapon = "nunchuks";

turtle = {
  name: name,
  mask: mask,
  weapon: weapon
};

output = turtle.name + " wears an " + turtle.mask + " mask. Watch out for his " + turtle.weapon + "!";
読み込み

字句スコープと変数の安全性

CoffeeScriptコンパイラは、すべての変数が字句スコープ内で適切に宣言されていることを確認します。自分で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();
読み込み
実行: inner

すべての変数の宣言が、最初に現れたときに最も近いスコープの先頭に移動されていることに注意してください。outerは、すでにスコープ内にあるため、内部関数内で再宣言されていません。一方、関数内のinnerは、同じ名前の外部変数の値を変更できないため、独自の宣言を持っています。

この動作は、Rubyのローカル変数のスコープと事実上同じです。varキーワードに直接アクセスできないため、意図的に外部変数をシャドウすることは不可能であり、参照するだけになります。したがって、深くネストされた関数を作成する場合は、誤って外部変数の名前を再利用していないか注意してください。

このドキュメントでは分かりやすさのために省略されていますが、すべてのCoffeeScript出力は匿名関数でラップされています: (function(){ … })(); この安全なラッパーと、varキーワードの自動生成により、グローバル名前空間を誤って汚染することが非常に困難になります。

他のスクリプトで使用できる最上位レベルの変数を作成する場合は、windowのプロパティとしてアタッチするか、CommonJSではexportsオブジェクトのプロパティとしてアタッチするか、exportを使用します。CommonJSとブラウザの両方をターゲットにしている場合は、存在演算子(後述)を使用すると、どこにそれらを追加するのかを確実に判断できます: exports ? this

If、Else、Unless、および条件付き代入

If/else文は、括弧と中括弧を使用せずに記述できます。関数やその他のブロック式と同様に、複数行の条件式はインデントで区切られます。また、ifまたはunlessを最後に付ける便利な後置形式もあります。

CoffeeScriptは、可能な場合は三項演算子を使用して、そうでない場合はクロージャラッピングを使用して、if文をJavaScript式にコンパイルできます。CoffeeScriptには明示的な三項演算子はありません。単一行で通常のif文を使用するだけです。

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;
読み込み

スプラット…

JavaScriptのargumentsオブジェクトは、可変数の引数を受け入れる関数を使用するのに役立つ方法です。CoffeeScriptは、関数定義と呼び出しの両方でスプラット...を提供し、可変数の引数をより扱いやすくします。

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);
読み込み
実行

ループと内包表記

CoffeeScriptで記述するループのほとんどは、配列、オブジェクト、範囲に対する内包表記になります。内包表記は、オプションのガード句と現在の配列インデックスの値を使用して、forループを置き換え(そしてコンパイルします)。forループとは異なり、配列の内包表記は式であり、返却および代入できます。

# Eat lunch.
eat food for food in ['toast', 'cheese', 'wine']

# Fine five course dining.
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
menu i + 1, dish for dish, i in courses

# Health conscious meal.
foods = ['broccoli', 'spinach', 'chocolate']
eat food for food in foods when food isnt 'chocolate'
var courses, dish, food, foods, i, j, k, l, len, len1, len2, ref;

ref = ['toast', 'cheese', 'wine'];
for (j = 0, len = ref.length; j < len; j++) {
  food = ref[j];
  eat(food);
}

courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];

for (i = k = 0, len1 = courses.length; k < len1; i = ++k) {
  dish = courses[i];
  menu(i + 1, dish);
}

foods = ['broccoli', 'spinach', 'chocolate'];

for (l = 0, len2 = foods.length; l < len2; l++) {
  food = foods[l];
  if (food !== 'chocolate') {
    eat(food);
  }
}
読み込み

内包表記は、それ以外の場合はループ、each/forEachmap、またはselect/filterなどを使用するほとんどの場所で処理できるはずです。
shortNames = (name for name in list when name.length < 5)
ループの開始と終了がわかっている場合、または固定サイズの増分でステップ実行したい場合は、範囲を使用して内包表記の開始と終了を指定できます。

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;
})();
読み込み
実行: countdown

上記の例では、内包表記の値を変数に代入しているため、CoffeeScriptは各反復の結果を配列に収集しています。関数は、副作用のみを実行することを目的としたループで終わることがあります。このような場合、意味のある戻り値(trueなど)またはnullを関数の最後に追加することで、内包表記の結果を誤って返さないように注意してください。

固定サイズのチャンクで範囲の内包表記をステップ実行するには、byを使用します。例: evens = (x for x in [0..10] by 2)

現在の反復値が必要ない場合は、省略できます: browser.closeCurrentTab() for [0...count]

内包表記を使用して、オブジェクト内のキーと値を反復処理することもできます。配列内の値ではなく、オブジェクトのプロパティに対する内包表記を示すには、ofを使用します。

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;
})();
読み込み
実行: ages.join(", ")

プロトタイプから継承される可能性のあるプロパティを回避するために、hasOwnPropertyチェックを追加して、オブジェクト自体に定義されているキーのみを反復処理する場合は、for own key, value of objectを使用します。

ジェネレータ関数を反復処理するには、fromを使用します。ジェネレータ関数を参照してください。

CoffeeScriptが提供する唯一の低レベルループは、whileループです。JavaScriptとの主な違いは、whileループを式として使用でき、ループを通過する各反復の結果を含む配列を返すことです。

# Econ 101
if this.studyingEconomics
  buy()  while supply > demand
  sell() until supply > demand

# Nursery Rhyme
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;
})();
読み込み
実行: lyrics.join("\n")

可読性のために、untilキーワードはwhile notと等価であり、loopキーワードはwhile trueと等価です。

JavaScriptループを使用して関数を作成する場合、ループ変数を閉じ込み、生成されたすべての関数が最終値を共有しないようにするために、クロージャラッパーを挿入するのが一般的です。CoffeeScriptはdoキーワードを提供し、これは渡された関数をすぐに呼び出し、引数を転送します。

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);
}
読み込み

範囲を使用した配列のスライスとスプライシング

範囲を使用して、配列のスライスを抽出することもできます。2つのドット(3..6)を使用すると、範囲は包含的(3, 4, 5, 6)になります。3つのドット(3...6)を使用すると、範囲は終点を除外します(3, 4, 5)。スライスのインデックスには便利なデフォルトがあります。最初のインデックスを省略するとデフォルトでゼロになり、2番目のインデックスを省略するとデフォルトで配列のサイズになります。

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]

start   = numbers[0..2]

middle  = numbers[3...-2]

end     = numbers[-2..]

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, -2);

end = numbers.slice(-2);

copy = numbers.slice(0);
読み込み
実行: middle

同じ構文を代入で使用して、配列のセグメントを新しい値で置き換え、スプライシングすることもできます。

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;
読み込み
実行: numbers

JavaScript文字列は不変であり、スプライスできないことに注意してください。

すべてが式です(少なくとも、可能な限り)

CoffeeScript関数にreturn文を追加しなくても、最終値を返すことに気付いたかもしれません。CoffeeScriptコンパイラは、言語内のすべての文を式として使用できるようにしようとします。以下の関数では、returnが実行の各分岐にどのようにプッシュダウンされるかを見てください。

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";
読み込み
実行: eldest

関数は常に最終値を返しますが、完了したことがわかっている場合は、明示的なreturn(return value)を書き出すことで、関数本体から早期にreturnすることも、推奨される方法でもあります。

変数の宣言はスコープの先頭で行われるため、まだ見たことのない変数に対しても、式内で代入を使用できます。

six = (one = 1) + (two = 2) + (three = 3)
var one, six, three, two;

six = (one = 1) + (two = 2) + (three = 3);
読み込み
実行: six

それ以外の場合はJavaScriptの文であるものは、CoffeeScriptの式の一部として使用されると、クロージャでラップすることで式に変換されます。これにより、内包表記の結果を変数に代入するなど、便利なことができます。

# 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);
読み込み
実行: globals

try/catch文を関数呼び出しに直接渡すなど、ばかげたことにも役立ちます。

alert(
  try
    nonexistent / undefined
  catch error
    "And the error is ... #{error}"
)
var error;

alert((function() {
  try {
    return nonexistent / void 0;
  } catch (error1) {
    error = error1;
    return "And the error is ... " + error;
  }
})());
読み込み
実行

JavaScriptには、意味のある方法で式に変換できない文がいくつかあります。つまり、breakcontinue、およびreturnです。コードブロック内でそれらを使用する場合は、CoffeeScriptは変換を試みません。

演算子とエイリアス

==演算子は、望ましくない型強制を引き起こしやすく、非推移的であり、他の言語とは意味が異なるため、CoffeeScriptは=====に、!=!==にコンパイルします。さらに、is===に、isnt!==にコンパイルされます。

not!のエイリアスとして使用できます。

論理演算では、and&&に、or||にコンパイルされます。

改行またはセミコロンの代わりに、whileif/else、およびswitch/when文では、thenを使用して条件と式を区切ることができます。

YAMLと同様に、onyesはブール値trueと同じであり、offnoはブール値falseです。

unlessifの逆として使用できます。

this.propertyのショートカットとして、@propertyを使用できます。

inを使用して配列の存在をテストし、ofを使用してJavaScriptオブジェクトキーの存在をテストできます。

算術式を簡素化するために、**をべき乗に使用し、//を整数除算に使用します。%はJavaScriptと同じように機能しますが、%%「除数に依存する剰余」を提供します。

-7 % 5 == -2 # The remainder of 7 / 5
-7 %% 5 == 3 # n %% 5 is always between 0 and 4

tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length)
var modulo = function(a, b) { return (+a % (b = +b) + b) % b; };

-7 % 5 === -2;

modulo(-7, 5) === 3;

tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length));
読み込み

すべてまとめて

CoffeeScript JavaScript
is ===
isnt !==
not !
and &&
or ||
trueyeson true
falsenooff false
@this this
of in
in JSに相当するものなし
a ** b Math.pow(a, b)
a // b Math.floor(a / b)
a %% b (a % b + b) % b
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));
読み込み

存在演算子

JavaScriptでは、変数の存在をチェックするのは少し困難です。if (variable) …はそれに近いですが、ゼロ、空文字列、falseでは失敗します。CoffeeScriptの存在演算子?は、変数がnullまたはundefinedでない限りtrueを返し、Rubyのnil?と同様になります。

数値または文字列を処理する可能性のある場合、||=が提供するものよりも安全な条件付き代入にも使用できます。

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";
読み込み
実行: footprints

存在演算子のアクセサ変形?.を使用して、プロパティのチェーンでnull参照を吸収できます。基本値がnullまたはundefinedである可能性のある場合は、ドットアクセサ.の代わりに使用します。すべてプロパティが存在する場合は、期待される結果が得られます。チェーンが壊れている場合、それ以外の場合は発生するTypeErrorではなく、undefinedが返されます。

zip = lottery.drawWinner?().address?.zipcode
var ref, zip;

zip = typeof lottery.drawWinner === "function" ? (ref = lottery.drawWinner().address) != null ? ref.zipcode : void 0 : void 0;
読み込み

nullの吸収は、Rubyのandand gemおよびGroovyの安全なナビゲーション演算子に似ています。

クラス、継承、およびsuper

JavaScriptのプロトタイプ継承は常に少し複雑で、JavaScriptのプロトタイプの上に古典的な継承のためのよりクリーンな構文を提供するライブラリのファミリー全体があります。Base2Prototype.jsJS.Classなど。これらのライブラリは構文糖を提供しますが、組み込みの継承は、いくつかの小さな例外がなければ完全に使用できます。super(プロトタイプオブジェクトの現在の関数のインプリメンテーション)を呼び出すのが面倒で、プロトタイプチェーンを正しく設定するのが面倒です。

プロトタイプに繰り返し関数をアタッチする代わりに、CoffeeScriptは、クラスに名前を付け、スーパークラスを設定し、プロトタイププロパティを割り当て、コンストラクタを単一の割り当て可能な式で定義できる基本的なclass構造を提供します。

コンストラクタ関数は、役に立つスタックトレースをより適切にサポートするために名前が付けられています。以下の例にある最初のクラスでは、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,
  extend = 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; },
  hasProp = {}.hasOwnProperty;

Animal = (function() {
  function Animal(name) {
    this.name = name;
  }

  Animal.prototype.move = function(meters) {
    return alert(this.name + (" moved " + meters + "m."));
  };

  return Animal;

})();

Snake = (function(superClass) {
  extend(Snake, superClass);

  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(superClass) {
  extend(Horse, superClass);

  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();
読み込み
実行

プロトタイプを古典的に構成するのがお好きでない場合は、CoffeeScriptはいくつかの低レベルの利便性を提供します。extends演算子はプロトタイプの適切なセットアップに役立ち、任意のコンストラクタ関数のペア間の継承チェーンを作成するために使用できます。::はオブジェクトのプロトタイプへの迅速なアクセスを提供し、super()は同じ名前の直接の祖先のメソッドに対する呼び出しに変換されます。

String::dasherize = ->
  this.replace /_/g, "-"
String.prototype.dasherize = function() {
  return this.replace(/_/g, "-");
};
読み込み
実行: "one_two".dasherize()

最後に、クラス定義は実行可能なコードのブロックであり、興味深いメタプログラミングの可能性をもたらします。クラス定義のコンテキストでは、thisはクラスオブジェクト自体(コンストラクタ関数)であるため、@property: valueを使用して静的プロパティを割り当て、親クラスで定義された関数を呼び出すことができます: @attr 'title', type: 'text'

デストラクチャリング代入

JavaScript(ES2015以降)と同様に、CoffeeScriptにはデストラクチャリング代入構文があります。配列またはオブジェクトリテラルを値に代入する場合、CoffeeScriptは両方を分解して互いに照合し、右側の値を左側の変数に代入します。最も単純なケースでは、並列代入に使用できます。

theBait   = 1000
theSwitch = 0

[theBait, theSwitch] = [theSwitch, theBait]
var ref, theBait, theSwitch;

theBait = 1000;

theSwitch = 0;

ref = [theSwitch, theBait], theBait = ref[0], theSwitch = ref[1];
読み込み
実行: theBait

しかし、複数の値を返す関数に対処する場合にも役立ちます。

weatherReport = (location) ->
  # Make an Ajax request to fetch the weather...
  [location, 72, "Mostly Sunny"]

[city, temp, forecast] = weatherReport "Berkeley, CA"
var city, forecast, ref, temp, weatherReport;

weatherReport = function(location) {
  return [location, 72, "Mostly Sunny"];
};

ref = weatherReport("Berkeley, CA"), city = ref[0], temp = ref[1], forecast = ref[2];
読み込み
実行: forecast

デストラクチャリング代入は、任意の深さの配列およびオブジェクトのネストで使用して、深くネストされたプロパティを取り出すことができます。

futurists =
  sculptor: "Umberto Boccioni"
  painter:  "Vladimir Burliuk"
  poet:
    name:   "F.T. Marinetti"
    address: [
      "Via Roma 42R"
      "Bellagio, Italy 22021"
    ]

{sculptor} = futurists

{poet: {name, address: [street, city]}} = futurists
var city, futurists, name, ref, ref1, sculptor, street;

futurists = {
  sculptor: "Umberto Boccioni",
  painter: "Vladimir Burliuk",
  poet: {
    name: "F.T. Marinetti",
    address: ["Via Roma 42R", "Bellagio, Italy 22021"]
  }
};

sculptor = futurists.sculptor;

ref = futurists.poet, name = ref.name, (ref1 = ref.address, street = ref1[0], city = ref1[1]);
読み込み
実行: name + "-" + street

デストラクチャリング代入は、スプラットと組み合わせることもできます。

tag = "<impossible>"

[open, contents..., close] = tag.split("")
var close, contents, i, open, ref, tag,
  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++];
読み込み
実行: contents.join("")

展開を使用して、残りの値を代入することなく、配列の末尾から要素を取得できます。関数のパラメータリストでも機能します。

text = "Every literary critic believes he will
        outwit history and have the last word"

[first, ..., last] = text.split " "
var first, last, ref, text;

text = "Every literary critic believes he will outwit history and have the last word";

ref = text.split(" "), first = ref[0], last = ref[ref.length - 1];
読み込み
実行: first + " " + last

デストラクチャリング代入は、クラスコンストラクタと組み合わせてインスタンスのプロパティに、コンストラクタに渡されたオプションオブジェクトからの値を代入する場合にも便利です。

class Person
  constructor: (options) ->
    {@name, @age, @height = 'average'} = options

tim = new Person name: 'Tim', age: 4
var Person, tim;

Person = (function() {
  function Person(options) {
    var ref;
    this.name = options.name, this.age = options.age, this.height = (ref = options.height) != null ? ref : 'average';
  }

  return Person;

})();

tim = new Person({
  name: 'Tim',
  age: 4
});
読み込み
実行結果: tim.age + " " + tim.height

上記の例では、デストラクチャリングされたオブジェクトまたは配列にプロパティが欠けている場合、JavaScriptと同様にデフォルト値を指定できることも示しています。JavaScriptとの違いは、CoffeeScriptでは常にnullとundefinedを同じように扱う点です。

バインドされた関数、ジェネレータ関数

JavaScriptでは、thisキーワードは動的スコープを持ち、現在の関数がアタッチされているオブジェクトを意味します。関数をコールバックとして渡したり、別のオブジェクトにアタッチしたりすると、元のthisの値は失われます。この動作に慣れていない場合は、このDigital Webの記事で、その特異性について概観が得られます。

太い矢印=>を使用して、関数を定義し、その場で現在のthisの値にバインドすることができます。これは、PrototypeやjQueryのようなコールバックベースのライブラリを使用する場合、eachに渡すイテレータ関数を作成したり、onで使用するためのイベントハンドラ関数を作成する場合に役立ちます。太い矢印で作成された関数は、定義された場所でthisのプロパティにアクセスできます。

Account = (customer, cart) ->
  @customer = customer
  @cart = cart

  $('.shopping_cart').on 'click', (event) =>
    @customer.purchase @cart
var Account;

Account = function(customer, cart) {
  this.customer = customer;
  this.cart = cart;
  return $('.shopping_cart').on('click', (function(_this) {
    return function(event) {
      return _this.customer.purchase(_this.cart);
    };
  })(this));
};
読み込み

上記のコールバックで->を使用していた場合、@customerはDOM要素の未定義の "customer" プロパティを参照し、それにpurchase()を呼び出すと例外が発生します。

クラス定義で使用する場合、太い矢印で宣言されたメソッドは、インスタンスが構築されるときにクラスの各インスタンスに自動的にバインドされます。

CoffeeScript関数は、yieldキーワードを通じてES2015ジェネレータ関数もサポートしています。function*(){}のような冗長な記述はありません。CoffeeScriptのジェネレータは、単にyieldする関数です。

perfectSquares = ->
  num = 0
  loop
    num += 1
    yield num * num
  return

window.ps or= perfectSquares()
var perfectSquares;

perfectSquares = function*() {
  var num;
  num = 0;
  while (true) {
    num += 1;
    yield num * num;
  }
};

window.ps || (window.ps = perfectSquares());
読み込み
実行結果: ps.next().value

yield*yield fromと呼ばれ、yieldしないジェネレータを強制する必要がある場合はyield returnを使用できます。

for…fromを使用してジェネレータ関数を反復処理できます。

fibonacci = ->
  [previous, current] = [1, 1]
  loop
    [previous, current] = [current, previous + current]
    yield current
  return

getFibonacciNumbers = (length) ->
  results = [1]
  for n from fibonacci()
    results.push n
    break if results.length is length
  results
var fibonacci, getFibonacciNumbers;

fibonacci = function*() {
  var current, previous, ref, ref1;
  ref = [1, 1], previous = ref[0], current = ref[1];
  while (true) {
    ref1 = [current, previous + current], previous = ref1[0], current = ref1[1];
    yield current;
  }
};

getFibonacciNumbers = function(length) {
  var n, ref, results;
  results = [1];
  ref = fibonacci();
  for (n of ref) {
    results.push(n);
    if (results.length === length) {
      break;
    }
  }
  return results;
};
読み込み
実行結果: getFibonacciNumbers(10)

埋め込みJavaScript

できれば使用する必要はないでしょうが、CoffeeScriptの中にJavaScriptのスニペットを挿入する必要がある場合は、バッククォートを使用してそのまま渡すことができます。

hi = `function() {
  return [document.title, "Hello JavaScript"].join(": ");
}`
var hi;

hi = function() {
  return [document.title, "Hello JavaScript"].join(": ");
};
読み込み
実行結果: hi()

バッククォートはバックスラッシュでエスケープします: \`​`​ になります。

バッククォートの前にあるバックスラッシュは、さらにバックスラッシュでエスケープします: \\\`​\`​ になります。

markdown = `function () {
  return \`In Markdown, write code like \\\`this\\\`\`;
}`
var markdown;

markdown = function () {
  return `In Markdown, write code like \`this\``;
};
読み込み
実行結果: markdown()

トリプルバッククォートを使用してJavaScriptのブロックを埋め込むこともできます。バッククォートをエスケープするよりも簡単です(JavaScriptブロック内にバッククォートが必要な場合)。

```
function time() {
  return `The time is ${new Date().toLocaleTimeString()}`;
}
```

function time() {
  return `The time is ${new Date().toLocaleTimeString()}`;
}
;

読み込み
実行結果: time()

switch/when/else

JavaScriptのswitch文はやや扱いにくいです。case文の最後にbreakを記述して、誤ってデフォルトケースにフォールスルーすることを避ける必要があります。CoffeeScriptは誤ったフォールスルーを防ぎ、switchを返せる代入可能な式に変換できます。形式は次のとおりです。switch 条件、when 節、else デフォルトケース。

Rubyと同様に、CoffeeScriptのswitch文では、各when節に複数の値を指定できます。いずれかの値が一致すると、その節が実行されます。

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);
}
読み込み

switch文は制御式なしで使用することもでき、if/elseチェーンよりもすっきりとした代替手段となります。

score = 76
grade = switch
  when score < 60 then 'F'
  when score < 70 then 'D'
  when score < 80 then 'C'
  when score < 90 then 'B'
  else 'A'
# grade == 'C'
var grade, score;

score = 76;

grade = (function() {
  switch (false) {
    case !(score < 60):
      return 'F';
    case !(score < 70):
      return 'D';
    case !(score < 80):
      return 'C';
    case !(score < 90):
      return 'B';
    default:
      return 'A';
  }
})();
読み込み

try/catch/finally

try式はJavaScriptのtry文と同じセマンティクスを持ちますが、CoffeeScriptではcatchとfinallyの両方を省略できます。catch部分も、エラーパラメータが必要ない場合は省略できます。

try
  allHellBreaksLoose()
  catsAndDogsLivingTogether()
catch error
  print error
finally
  cleanUp()
var error;

try {
  allHellBreaksLoose();
  catsAndDogsLivingTogether();
} catch (error1) {
  error = error1;
  print(error);
} finally {
  cleanUp();
}
読み込み

連鎖比較

CoffeeScriptはPythonから連鎖比較を借用しており、値がある範囲内にあるかどうかを簡単にテストできます。

cholesterol = 127

healthy = 200 > cholesterol > 60
var cholesterol, healthy;

cholesterol = 127;

healthy = (200 > cholesterol && cholesterol > 60);
読み込み
実行結果: healthy

文字列補間、ブロック文字列、ブロックコメント

Rubyスタイルの文字列補間がCoffeeScriptに含まれています。二重引用符で囲まれた文字列では、#{ … }を使用して補間された値を使用でき、単一引用符で囲まれた文字列はリテラルです。オブジェクトキーでも補間を使用できます。

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 π";
読み込み
実行結果: sentence

CoffeeScriptでは複数行の文字列が許可されています。行末にバックスラッシュがない限り、行は1つのスペースで結合されます。インデントは無視されます。

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...";
読み込み
実行結果: mobyDick

ブロック文字列は、フォーマットされたテキストまたはインデントに依存するテキスト(または、単に引用符とアポストロフィのエスケープをしたくない場合)を保持するために使用できます。ブロックを開始するインデントレベルは全体を通して維持されるため、コードの本体に合わせてすべてを揃えることができます。

html = """
       <strong>
         cup of coffeescript
       </strong>
       """
var html;

html = "<strong>\n  cup of coffeescript\n</strong>";
読み込み
実行結果: html

二重引用符で囲まれたブロック文字列は、他の二重引用符で囲まれた文字列と同様に、補間を許可します。

生成されたJavaScriptにブロックコメントを渡したい場合があります。たとえば、ファイルの先頭にライセンスヘッダーを埋め込む必要がある場合などです。ブロック文字列の構文を反映したブロックコメントは、生成されたコードに保持されます。

###
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
###

/*
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
 */

読み込み

タグ付きテンプレートリテラル

CoffeeScriptはES2015タグ付きテンプレートリテラルをサポートしており、カスタム文字列補間を有効にします。文字列の前に関数名を直接記述した場合(間にスペースはありません)、CoffeeScriptは「関数と文字列」の組み合わせをES2015タグ付きテンプレートリテラルとして出力します。これは適切に動作します。関数は、補間された文字列を構成する入力テキストと式の部分をパラメータとして呼び出されます。その後、関数はこれらの部分を出力文字列に組み立てて、カスタム文字列補間を提供します。

CoffeeScriptコンパイラはこの機能に対してES2015構文を出力していることに注意してください。そのため、コードを動作させるには、ターゲットJavaScriptランタイムがES2015構文をサポートしている必要があります。または、BabelTraceur Compilerなどのツールを使用して、このES2015構文を互換性のあるJavaScriptに変換することができます。

upperCaseExpr = (textParts, expressions...) ->
  textParts.reduce (text, textPart, i) ->
    text + expressions[i - 1].toUpperCase() + textPart

greet = (name, adjective) ->
  upperCaseExpr"""
               Hi #{name}. You look #{adjective}!
               """
var greet, upperCaseExpr,
  slice = [].slice;

upperCaseExpr = function() {
  var expressions, textParts;
  textParts = arguments[0], expressions = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  return textParts.reduce(function(text, textPart, i) {
    return text + expressions[i - 1].toUpperCase() + textPart;
  });
};

greet = function(name, adjective) {
  return upperCaseExpr`Hi ${name}. You look ${adjective}!`;
};
読み込み
実行結果: greet("greg", "awesome")

ブロック正規表現

ブロック文字列とコメントと同様に、CoffeeScriptはブロック正規表現をサポートしています。これは、内部の空白を無視し、コメントと補間を含むことができる拡張正規表現です。Perlの/x修飾子をモデルにしたCoffeeScriptのブロック正規表現は///で区切られており、複雑な正規表現を読みやすくする上で大きな役割を果たします。CoffeeScriptソースからの引用として

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})/;
読み込み

モジュール

ES2015モジュールは、非常に類似したimportおよびexport構文でCoffeeScriptでサポートされています。

import 'local-file.coffee'
import 'coffeescript'

import _ from 'underscore'
import * as underscore from 'underscore'

import { now } from 'underscore'
import { now as currentTimestamp } from 'underscore'
import { first, last } from 'underscore'
import utilityBelt, { each } from 'underscore'

export default Math
export square = (x) -> x * x
export class Mathematics
  least: (x, y) -> if x < y then x else y

export { sqrt }
export { sqrt as squareRoot }
export { Mathematics as default, sqrt as squareRoot }

export * from 'underscore'
export { max, min } from 'underscore'
import 'local-file.coffee';

import 'coffeescript';

import _ from 'underscore';

import * as underscore from 'underscore';

import {
  now
} from 'underscore';

import {
  now as currentTimestamp
} from 'underscore';

import {
  first,
  last
} from 'underscore';

import utilityBelt, {
  each
} from 'underscore';

export default Math;

export var square = function(x) {
  return x * x;
};

export var Mathematics = (function() {
  function Mathematics() {}

  Mathematics.prototype.least = function(x, y) {
    if (x < y) {
      return x;
    } else {
      return y;
    }
  };

  return Mathematics;

})();

export {
  sqrt
};

export {
  sqrt as squareRoot
};

export {
  Mathematics as default,
  sqrt as squareRoot
};

export * from 'underscore';

export {
  max,
  min
} from 'underscore';
読み込み

CoffeeScriptコンパイラはモジュールを解決しません。CoffeeScriptでimportまたはexport文を書くと、結果の出力にimportまたはexport文が生成されます。このES2015構文をターゲットランタイムで動作するコードに変換するには、Traceur CompilerBabelRollupなどの別のトランスパイラをアタッチする必要があります。

また、importまたはexport文を含むファイルは、トップレベル関数セーフティラッパーなしで出力されることにも注意してください。つまり、モジュールのインポートまたはエクスポートは、そのファイルに対してベアモードを自動的にトリガーします。これは、ES2015仕様では、importまたはexport文は最上位スコープで発生する必要があるためです。

CakeとCakefile

CoffeeScriptには、MakeRakeに似た(非常に)シンプルなビルドシステムが含まれています。当然のことながら、Cakeと呼ばれ、CoffeeScript言語自体をビルドおよびテストするタスクに使用されます。タスクはCakefileという名前のファイルで定義され、ディレクトリ内からcake [task]を実行することで呼び出すことができます。すべてのタスクとオプションのリストを出力するには、cakeと入力するだけです。

タスク定義はCoffeeScriptで記述されているため、Cakefileに任意のコードを配置できます。名前、長い説明、タスクの実行時に呼び出す関数を指定してタスクを定義します。タスクがコマンドラインオプションを受け取る場合、短縮形と完全なフラグを指定してオプションを定義でき、optionsオブジェクトで使用できるようになります。これは、Node.js APIを使用して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);
});
読み込み

たとえば、testの前にbuildを実行するなど、あるタスクを別のタスクの前に呼び出す必要がある場合は、invoke関数を使用できます。invoke 'build'。Cakeタスクは、CoffeeScript関数をコマンドラインに公開するための最小限の方法であるため、組み込みの高度な機能は期待しないでください。依存関係または非同期コールバックが必要な場合は、Cakeタスクではなく、コード自体に配置することをお勧めします。

ソースマップ

CoffeeScript 1.6.1以降には、ソースマップの生成がサポートされています。これは、JavaScriptエンジンにCoffeeScriptプログラムのどの部分が評価されているコードと一致するかを伝える方法です。これをサポートするブラウザは、ソースマップを使用してデバッガに元のソースコードを自動的に表示できます。JavaScriptファイルとともにソースマップを生成するには、コンパイラに--mapまたは-mフラグを渡します。

ソースマップ、その動作、ブラウザでの接続方法に関する完全な紹介については、HTML5チュートリアルをお読みください。

“text/coffeescript”スクリプトタグ

本格的な用途にはお勧めしませんが、CoffeeScriptは<script type="text/coffeescript">タグを使用してブラウザに直接含めることができます。ソースには、コンパイラの圧縮および縮小バージョンが含まれています(現在のバージョンをダウンロード、gzip圧縮時は51kdocs/v1/browser-compiler/coffee-script.jsとして。このファイルをインラインCoffeeScriptタグを含むページに含めると、順番にコンパイルして評価されます。

実際、上記の「Try CoffeeScript」を実行する小さな接着剤スクリプトと、メニューのjQueryは、まさにこの方法で実装されています。ソースを表示し、ページの一番下を見て例を確認してください。スクリプトを含めると、CoffeeScript.compile()にアクセスできるようになるため、Firebugを開いて文字列をコンパイルできます。

CoffeeScriptに関する通常の注意事項が適用されます。インラインスクリプトはクロージャラッパー内で実行されるため、グローバル変数または関数を公開する場合は、windowオブジェクトにアタッチします。

書籍

CoffeeScriptの学習を始めるのに役立つ優れたリソースがいくつかあり、その一部はオンラインで無料で入手できます。

スクリーンキャスト

オープンソースのCoffeeScript例は、GitHubのベストリストで見つけることができます。いくつか例を挙げると:

リソース

Webチャット(IRC)

迅速なヘルプとアドバイスは、通常CoffeeScriptのIRCルームで得られます。`irc.freenode.net`の`#coffeescript`に参加するか、下のボタンをクリックしてこのページでWebチャットセッションを開きます。

変更ログ

1.12.7

1.12.6

1.12.5

1.12.4

1.12.3

1.12.2

1.12.1

1.12.0

1.11.1

1.11.0

1.10.0

1.9.3

1.9.2

1.9.1

1.9.0

1.8.0

1.7.1

1.7.0

$ 'body'
.click (e) ->
  $ '.box'
  .fadeIn 'fast'
  .addClass '.active'
.css 'background', 'white'
$('body').click(function(e) {
  return $('.box').fadeIn('fast').addClass('.active');
}).css('background', 'white');
読み込み

1.6.3

1.6.2

1.6.1

1.5.0

1.4.0

1.3.3

1.3.1

1.2.0

1.1.3

1.1.2

ブロックコメントのフォーマット、?=コンパイル、制御構造に対する暗黙の呼び出し、try/catchブロックの暗黙的な呼び出し、ローカルスコープからの可変引数のリーク、heregexesに続く構文エラーの行番号、括弧で囲まれた数値リテラルのプロパティアクセス、予約名を使用したバインドされたクラスメソッドとsuper、REPLのオーバーホール、連続したコンパイル済みセミコロン、暗黙的に呼び出されたオブジェクト内のブロックコメント、およびChromeのバグに関する修正。

1.1.1

外部コンストラクタ関数を持つクラスのバグ修正リリース、issue #1182を参照。

1.1.0

coffee実行可能ファイルを使用して実行する場合、process.argvなどはnodeではなくcoffeeを報告するようになりました。Node.js 0.4.xモジュールのルックアップの変更との互換性が向上しました。REPLの出力がNodeのもののようにカラー化されるようになりました。--joinを使用する際に連結されたCoffeeScriptに名前を付けることが必須になりました。複合除算/=を誤って正規表現としてレキシングする問題を修正しました。すべてのtext/coffeescriptタグは、含まれている順序で実行されるようになりました。外部コンストラクタ関数を使用する拡張サブクラスの問題を修正しました。addImplicitParenthesesの極端なケースの無限ループを修正しました。長い関数呼び出しチェーンでの指数関数的な遅延を修正しました。グローバル変数はCoffeeScript REPLにリークしなくなりました。スプラットされたパラメータは関数に対してローカルに宣言されます。

1.0.1

Unicode識別子に関するレキサーのバグを修正しました。Node.js 0.3.7との互換性のためにREPLを更新しました。REPLでの相対パスの要求を修正しました。末尾のreturnreturn undefinedは、最適化されて削除されるようになりました。Node.js 0.2.5との後方互換性のために、コアNode.js utilモジュールの要求を停止しました。条件付きreturnswitch文でフォールスルーを引き起こすケースを修正しました。非構造化代入における空のオブジェクトを最適化しました。

1.0.0

CoffeeScriptループは、ループ本体内で関数が生成されている場合、ブロックスコープを保持しようとしないようになりました。代わりに、doキーワードを使用して便利なクロージャラッパーを作成できます。node実行可能ファイルに直接オプションを渡すための--nodejsフラグを追加しました。式内の純粋なステートメントの使用に関する動作が改善されました。すべてのブラウザで-1による包括的なスライス、およびエンドポイントとして任意の式を使用したスプライシングを修正しました。

0.9.6

REPLは、スタックトレースを適切にフォーマットし、非同期例外の間もアクティブな状態を維持するようになりました。--watchを使用すると、ファイルがコンパイルされるときにタイムスタンプが出力されるようになりました。摘出されたクロージャループ内で誤ってリークしていた変数を修正しました。コンストラクタは、クラス本体内の宣言位置を維持するようになりました。動的なオブジェクトキーは削除されました。ネストされたクラスがサポートされるようになりました。裸のスプラットされた関数の実行コンテキストを修正しました。チェーンされた比較の反転のバグを修正しました。チェーンされたクラスのインスタンス化は、スプラットで適切に機能するようになりました。

0.9.5

0.9.5は、CoffeeScript 1.0の最初のリリース候補と見なすことができます。以前のリリース以降、内部的な変更が多数行われており、その多くはsatyrのCoffeeScriptの方言であるCocoから貢献されています。Heregex(拡張正規表現)が追加されました。関数は、デフォルトの引数を指定できるようになりました。クラス本体は、実行可能なコードになりました。無効なCoffeeScriptに対する構文エラーが改善されました。undefinednullのように動作するようになり、新しい値を代入できなくなりました。単一行のリスト内包表記に関して優先順位の変更がありました: result = i for i in listは、デフォルトでresult = (i for i in list)として解析されていましたが…現在は(result = i) for i in listとして解析されます。

0.9.4

CoffeeScriptは、適切に名前付けされた一時変数を使用し、使用後に参照をリサイクルするようになりました。Node.js 0.3require.extensionsサポートを追加しました。ブラウザでCoffeeScriptを読み込むと、グローバルスコープに単一のCoffeeScriptオブジェクトが追加されるようになりました。暗黙的なオブジェクトとブロックコメントの極端なケースの修正。

0.9.3

CoffeeScriptのswitch文は、JSのswitch文にコンパイルされるようになりました。以前はJavaScript 1.3との互換性のためにif/elseチェーンにコンパイルされていました。関数の呼び出しのソーキングがサポートされるようになりました。RubyMineエディタのユーザーは、--watchモードを使用できるようになりました。

0.9.2

範囲リテラルの開始と終了の指定はオプションになりました(例: array[3..])。a not instanceof bと言うことができます。ネストされた重要なインデントと重要ではないインデントに関する重要なバグを修正しました(Issue #637)。coffeeコマンドにフックできる--requireフラグを追加しました。優先するJavaScriptLint設定のためのカスタムjsl.confファイルを追加しました。演算のルールをフラット化することで、Jison文法のコンパイル時間を短縮しました。ブロックコメントは、JavaScript縮小ツールに優しい構文で使用できるようになりました。JavaScriptの複合代入ビット演算子を追加しました。暗黙的なオブジェクトリテラルの先頭に数値キーと文字列キーがある場合、暗黙の呼び出しの対象として、および複合代入の一部として、バグを修正しました。

0.9.1

0.9.1のバグ修正リリースです。混合された暗黙的なオブジェクト、暗黙的な関数呼び出し、および暗黙的なインデントの処理が大幅に向上しました。文字列と正規表現の補間は、厳密に#{ … }(Rubyスタイル)になりました。コンパイラは、コンパイル前に実行するスクリプトを指定する--requireフラグを受け取るようになりました。

0.9.0

CoffeeScript 0.9 シリーズは、1.0 のリリース候補とみなされています。徹底的なテストを行いましょう。0.9.0 では、後方互換性のない大きな変更が導入されました。代入には = を、オブジェクトリテラルには : を使用するようになりました(JavaScript と同じです)。これにより、暗黙的なオブジェクトリテラルと YAML スタイルのオブジェクト定義が可能になります。+=or= などに置き換え、ハーフアサインメントは削除されました。補間はドル記号 $ の代わりにハッシュマーク # を使用するようになりました — ドル記号は有効な JS の識別子の部分になる可能性があるためです。下向き範囲内包表記が再び安全になり、整数端点で作成された場合は、通常の for ループに最適化されます。高速でガードのないオブジェクト内包表記の形式が追加されました: for all key, value of object。引数なしで super キーワードを指定すると、Ruby と同様に、関数に渡されたすべての引数が転送されるようになりました。親クラス A からクラス B を拡張する場合、Aextended メソッドが定義されていると、B を渡して呼び出されます — これにより、静的継承などが可能になります。太い矢印でバインドされた関数の出力がきれいになりました。@variables をパラメータリストで使用できるようになりました。パラメータはオブジェクトのプロパティとして自動的に設定されます — コンストラクタとセッター関数で役立ちます。コンストラクタ関数は、スプラットを受け取ることができるようになりました。

0.7.2

coffee コマンドラインオプションが特定の状況で解析されない問題に対する迅速なバグ修正(0.7.1 の直後)。

0.7.1

ブロックスタイルのコメントがそのまま渡され、JavaScript のブロックコメントとして出力されるようになりました。ライセンスや著作権ヘッダーに役立ちます。ハッシュバングを使用した CoffeeScript のスタンドアロン実行のサポートが向上しました。文法にないトークンに対する構文エラーが改善されました。

0.7.0

CoffeeScript の公式変数スタイルは、JavaScript と同様に camelCase になりました。予約語をオブジェクトキーとして使用できるようになり、自動的に引用符で囲まれます。範囲内包表記はよりクリーンなコードを生成するようになりましたが、下向きに反復処理するには by -1 を指定する必要があります。構文エラーのレポートが前のリリースから大幅に改善されました。引数なしで coffee を実行すると、Readline サポート付きの REPL が起動します。<- バインド演算子は CoffeeScript から削除されました。while true ループに相当する loop キーワードが追加されました。クロージャを含む内包表記は、forEach のセマンティクスのように、その変数を閉じ込めます。クラス定義内でバインド関数を(インスタンスにバインドして)使用できるようになりました。一貫性のため、a in b は配列の存在チェックになり、a of b はオブジェクトキーチェックになりました。コメントは生成された JavaScript に渡されなくなりました。

0.6.2

coffee コマンドは、スクリプトのディレクトリ全体をコンパイルする際、ディレクトリ構造を保持するようになりました。CoffeeScript コンパイラが Internet Explorer 内でライブ実行されないのを防いでいた 2 つの欠落を修正しました。CoffeeScript の heredoc と同様のブロックコメントの構文が追加されました。プロパティの名前と値の名前が同じである ECMA Harmony DRY スタイルのパターンマッチングがサポートされるようになりました: {name, length}: func。内包表記変数内でパターンマッチングが許可されるようになりました。ブロック形式で unless が許可されるようになりました。while ループの逆として until ループが追加されました。スイッチオブジェクト節なしで switch 文が許可されるようになりました。Node.js v0.1.95 と互換性があります。

0.6.1

新しい Node.js v0.1.90 シリーズとの互換性のために CoffeeScript がアップグレードされました。

0.6.0

Python のように、末尾のカンマが許可されるようになりました。@property 表記を使用して、クラス定義内で静的プロパティを直接代入できるようになりました。

0.5.6

補間を正規表現、heredoc、文字列内で使用できるようになりました。<- バインド演算子が追加されました。特別な ||= スタイルの演算子の代わりに、ハーフ式への代入を許可しました。引数オブジェクトは、配列に自動変換されなくなりました。coffee-script を require した後、registerExtension のおかげで、Node.js は .coffee ファイルを直接ロードできるようになりました。関数呼び出し、配列、パターンマッチングで複数のスプラットを使用できるようになりました。

0.5.5

Stan Angeloff 氏による文字列補間の寄稿。0.5.3 以降、--run がデフォルトになっているため、--stdio--eval もデフォルトで実行されるように更新されました。結果を出力したい場合は、--compile も渡してください。

0.5.4

Node.js のグローバル定数 __filename__dirname を修正するバグ修正。ネストされた関数リテラルとインデントが不適切なコメントのより柔軟な解析のための調整。最新の Node.js API への更新。

0.5.3

CoffeeScript にクラス定義の構文が追加されました。コアコンポーネント(ノード、字句解析器、書き換え器、スコープ、Optparse)の多くがそれらを使用しています。Cakefile は optparse.coffee を使用して、タスクのオプションを定義できます。coffee コマンドのデフォルトフラグは --run になり、JavaScript を保存するには --compile を使用します。正規表現リテラルと連結除算のあいまいさに関するバグ修正。

0.5.2

ウェブページに含めるためのコンパイラの圧縮版(browser-compiler/coffee-script.js)が追加されました。タイプが text/coffeescript のスクリプトタグを自動的に実行します。パイプで入力されたコンパイル用の --stdio オプションが coffee コマンドに追加されました。

0.5.1

存在演算子を使用した null ソーキングの改善(インデックス付きプロパティのソーキングを含む)。while ループに条件が追加され、内包表記と同様に when を使用してフィルタとして使用できるようになりました。

0.5.0

CoffeeScript 0.5.0 はメジャーリリースです。言語の変更はありませんが、Ruby コンパイラが削除され、純粋な CoffeeScript で記述されたセルフホスティングコンパイラに置き換えられました。

0.3.2

@propertythis.property の省略形になりました。デフォルトの JavaScript エンジンが Narwhal から Node.js に変更されました。引き続き Narwhal を使用したい場合は、--narwhal フラグを渡してください。

0.3.0

CoffeeScript 0.3 には、主要な構文の変更が含まれています。関数記号が -> に変更され、バインド関数の記号は => になりました。関数定義のパラメータリストは、括弧で囲む必要があります。?. 演算子を使用してプロパティソーキングが追加されました。引数付きの関数を呼び出す場合、括弧を省略可能にしました。廃止されたブロックリテラル構文を削除しました。

0.2.6

Python スタイルの連結比較、条件付き存在演算子 ?=、および *Beautiful Code* からのいくつかの例を追加しました。ステートメントから式への変換、引数から配列への変換、および TextMate 構文ハイライターに関するバグ修正。

0.2.5

switch 文の条件で複数の値を一度に指定できるようになりました — それらのいずれかが true の場合、そのケースが実行されます。this に関数を定義してすぐにバインドする長い矢印 ==> を追加しました。内包表記と同様に、while ループを式として使用できるようになりました。パターンマッチ内でスプラットを使用して、配列の残りを吸収できます。

0.2.4

ネストされた配列とオブジェクトから値を抽出するための、ECMAScript Harmony スタイルのデストラクチャリング代入を追加しました。インデントに依存する heredoc を追加し、きれいにフォーマットされた文字列やコードチャンクを作成します。

0.2.3

不十分な ino キーワードを削除し、オブジェクト内包表記に of を使用して置き換えられました。これにより、次のように記述できるようになりました: for prop, value of object

0.2.2

オブジェクトを対象とした内包表記を実行する際には、コンパイル時により小さく、効率的なコードを生成するために、in の代わりに ino を使用します。.prototype. の省略形として :: を追加しました。「スプラット」記号は、プレフィックスのアスタリスク * から、ポストフィックスの省略記号 ... に変更されました。JavaScript の in 演算子、空の return 文、空の while ループを追加しました。大文字で始まるコンストラクタ関数は、オブジェクトの新しいインスタンスが返されることを確認するための安全チェックを含みます。extends キーワードは、Google の Closure Library の goog.inherits と同じように機能するようになりました。

0.2.1

参照されたときに、引数オブジェクトが実際の配列に変換されるようになりました。

0.2.0

メジャーリリース。重要な空白処理。ステートメントから式への変換の改善。スプラット。スプライスリテラル。オブジェクト内包表記。ブロック。存在演算子。問題を投稿してくれた皆さんに感謝します。Liam O’Connor-Davis 氏には、空白処理と式のヘルプに関して特に感謝しています。

0.1.6

CoffeeScriptディレクトリ外から`coffee --interactive`および`--run`を実行する際のバグ修正。ネストされた関数/if文のバグ修正。

0.1.5

配列スライスリテラルと配列内包表記は、開始と終了を指定するためにRubyスタイルの範囲を使用できるようになりました。JavaScriptの変数宣言はスコープの先頭に移動されるようになり、すべての代入文が式になります。`\`を使用して改行をエスケープできます。`coffee-script`コマンドは`coffee`に変更されました。

0.1.4

公式のCoffeeScript拡張子は、C#に適切に属する` .cs`ではなく` .coffee`になりました。多くの要望に応え、`=`を使用して代入することもできるようになりました。JavaScriptとは異なり、`=`はオブジェクトリテラル内でも`:`と置き換え可能に使用できます。`func(1)(2)(3)(4)`のような連鎖した関数呼び出しの文法的な修正を行いました。継承とsuperは`__proto__`を使用しなくなったため、IEと互換性があるはずです。

0.1.3

`coffee`コマンドに`--interactive`が追加されました。これは対話型のCoffeeScriptセッションを起動します。また、`--run`はスクリプトを直接コンパイルして実行します。両方のオプションは、Narwhalの動作するインストールに依存します。`aint`キーワードは`isnt`に置き換えられました。これは`is`とよりスムーズに連携します。引用符で囲まれた文字列は、オブジェクトリテラル内で識別子として許可されるようになりました(例:`{"5+5": 10}`)。すべての代入演算子はコロンを使用するようになりました:`+:`, `-:`, `*:`, など。

0.1.2

`extends`キーワードの再追加により、複数のレベルの継承を通して`super()`を呼び出す際のバグを修正しました。実験的なNarwhalサポート(Tuskパッケージとして)を追加しました(Tom Robinson提供)。これには、CoffeeScript REPLおよびインタープリターとしての**bin/cs**が含まれます。安全な関数ラッパーを抑制するための新しい`--no-wrap`オプション。

0.1.1

`instanceof`と`typeof`を演算子として追加しました。

0.1.0

CoffeeScriptの最初のリリース。