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
/await
、JSX、オブジェクトのレスト/スプレッド構文、および最新の構文を使用して生成された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;
})();
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」ヘッダーを抑制します。 |
src
にある.coffee
ファイルのディレクトリツリーを、lib
にある.js
ファイルの並列ツリーにコンパイルします。coffee --compile --output lib/ src/
coffee --watch --compile experimental.coffee
coffee --join project.js --compile src/*.coffee
coffee -bpe "alert i for i in [0..10]"
coffee -o lib/ -cw src/
Ctrl-D
、複数行を入力するにはCtrl-V
)。coffee
通常のプログラミング言語として使用される以外にも、CoffeeScriptは「リテラシー」モードで記述することもできます。ファイルを.litcoffee
拡張子で名前付けると、Markdownドキュメントとして記述できます。これは、実行可能なCoffeeScriptコードでもあるドキュメントです。コンパイラは、インデントされたブロック(Markdownによるソースコードの表示方法)をコードとして扱い、残りの部分をコメントとして無視します。
ちょっとした遊びとして、コンパイラの少しの部分が現在この方法で実装されています。ドキュメントとして、raw、およびテキストエディタで適切に強調表示されています。
このリファレンスは、必要に応じて上から下まで読むことができるように構成されています。後のセクションでは、以前に紹介したアイデアと構文を使用しています。JavaScriptの知識があることを前提としています。次の例ではすべて、ソースCoffeeScriptが左側に、JavaScriptへの直接コンパイルが右側に表示されます。
多くの例は(意味をなす場合)、右側の実行ボタンを押して実行でき、左側の読み込みボタンを押して「CoffeeScriptを試す」コンソールに読み込むことができます。
まず、基本事項です。CoffeeScriptは、コードのブロックを区切るために重要な空白を使用します。式を終了するためにセミコロン;
を使用する必要はありません。行を終了するだけで十分です(ただし、複数の式を1行に収めるためにセミコロンを使用することもできます)。関数、if文、switch、およびtry/catchでコードのブロックを囲むために中括弧{ }
を使用する代わりに、インデントを使用します。
引数を渡す場合、関数を呼び出すために括弧を使用する必要はありません。暗黙の呼び出しは、行またはブロック式の終わりまで継続します。
console.log sys.inspect object
→ console.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;
};
関数には、引数にデフォルト値を設定することもできます。これは、入力引数が不足している場合(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 + "...";
};
オブジェクトと配列の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
}
};
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();
すべての変数の宣言が、最初に現れたときに最も近いスコープの先頭に移動されていることに注意してください。outerは、すでにスコープ内にあるため、内部関数内で再宣言されていません。一方、関数内のinnerは、同じ名前の外部変数の値を変更できないため、独自の宣言を持っています。
この動作は、Rubyのローカル変数のスコープと事実上同じです。var
キーワードに直接アクセスできないため、意図的に外部変数をシャドウすることは不可能であり、参照するだけになります。したがって、深くネストされた関数を作成する場合は、誤って外部変数の名前を再利用していないか注意してください。
このドキュメントでは分かりやすさのために省略されていますが、すべてのCoffeeScript出力は匿名関数でラップされています: (function(){ … })();
この安全なラッパーと、var
キーワードの自動生成により、グローバル名前空間を誤って汚染することが非常に困難になります。
他のスクリプトで使用できる最上位レベルの変数を作成する場合は、windowのプロパティとしてアタッチするか、CommonJSではexportsオブジェクトのプロパティとしてアタッチするか、export
文を使用します。CommonJSとブラウザの両方をターゲットにしている場合は、存在演算子(後述)を使用すると、どこにそれらを追加するのかを確実に判断できます: exports ? this
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/forEach、map、または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;
})();
上記の例では、内包表記の値を変数に代入しているため、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;
})();
プロトタイプから継承される可能性のあるプロパティを回避するために、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;
})();
可読性のために、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);
同じ構文を代入で使用して、配列のセグメントを新しい値で置き換え、スプライシングすることもできます。
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;
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";
関数は常に最終値を返しますが、完了したことがわかっている場合は、明示的なreturn(return value
)を書き出すことで、関数本体から早期にreturnすることも、推奨される方法でもあります。
変数の宣言はスコープの先頭で行われるため、まだ見たことのない変数に対しても、式内で代入を使用できます。
six = (one = 1) + (two = 2) + (three = 3)
var one, six, three, two;
six = (one = 1) + (two = 2) + (three = 3);
それ以外の場合は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);
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には、意味のある方法で式に変換できない文がいくつかあります。つまり、break
、continue
、およびreturn
です。コードブロック内でそれらを使用する場合は、CoffeeScriptは変換を試みません。
==
演算子は、望ましくない型強制を引き起こしやすく、非推移的であり、他の言語とは意味が異なるため、CoffeeScriptは==
を===
に、!=
を!==
にコンパイルします。さらに、is
は===
に、isnt
は!==
にコンパイルされます。
not
を!
のエイリアスとして使用できます。
論理演算では、and
は&&
に、or
は||
にコンパイルされます。
改行またはセミコロンの代わりに、while、if/else、およびswitch/when文では、then
を使用して条件と式を区切ることができます。
YAMLと同様に、on
とyes
はブール値true
と同じであり、off
とno
はブール値false
です。
unless
はif
の逆として使用できます。
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 |
|| |
true 、yes 、on |
true |
false 、no 、off |
false |
@ 、this |
this |
of |
in |
in |
JSに相当するものなし |
a ** b |
|
a // b |
|
a %% 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";
存在演算子のアクセサ変形?.
を使用して、プロパティのチェーンで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の安全なナビゲーション演算子に似ています。
JavaScriptのプロトタイプ継承は常に少し複雑で、JavaScriptのプロトタイプの上に古典的な継承のためのよりクリーンな構文を提供するライブラリのファミリー全体があります。Base2、Prototype.js、JS.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, "-");
};
最後に、クラス定義は実行可能なコードのブロックであり、興味深いメタプログラミングの可能性をもたらします。クラス定義のコンテキストでは、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];
しかし、複数の値を返す関数に対処する場合にも役立ちます。
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];
デストラクチャリング代入は、任意の深さの配列およびオブジェクトのネストで使用して、深くネストされたプロパティを取り出すことができます。
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]);
デストラクチャリング代入は、スプラットと組み合わせることもできます。
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++];
展開を使用して、残りの値を代入することなく、配列の末尾から要素を取得できます。関数のパラメータリストでも機能します。
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];
デストラクチャリング代入は、クラスコンストラクタと組み合わせてインスタンスのプロパティに、コンストラクタに渡されたオプションオブジェクトからの値を代入する場合にも便利です。
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
});
上記の例では、デストラクチャリングされたオブジェクトまたは配列にプロパティが欠けている場合、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());
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;
};
できれば使用する必要はないでしょうが、CoffeeScriptの中にJavaScriptのスニペットを挿入する必要がある場合は、バッククォートを使用してそのまま渡すことができます。
hi = `function() {
return [document.title, "Hello JavaScript"].join(": ");
}`
var hi;
hi = function() {
return [document.title, "Hello JavaScript"].join(": ");
};
バッククォートはバックスラッシュでエスケープします: \`
は `
になります。
バッククォートの前にあるバックスラッシュは、さらにバックスラッシュでエスケープします: \\\`
は \`
になります。
markdown = `function () {
return \`In Markdown, write code like \\\`this\\\`\`;
}`
var markdown;
markdown = function () {
return `In Markdown, write code like \`this\``;
};
トリプルバッククォートを使用してJavaScriptのブロックを埋め込むこともできます。バッククォートをエスケープするよりも簡単です(JavaScriptブロック内にバッククォートが必要な場合)。
```
function time() {
return `The time is ${new Date().toLocaleTimeString()}`;
}
```
function time() {
return `The time is ${new Date().toLocaleTimeString()}`;
}
;
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式は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);
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 π";
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...";
ブロック文字列は、フォーマットされたテキストまたはインデントに依存するテキスト(または、単に引用符とアポストロフィのエスケープをしたくない場合)を保持するために使用できます。ブロックを開始するインデントレベルは全体を通して維持されるため、コードの本体に合わせてすべてを揃えることができます。
html = """
<strong>
cup of coffeescript
</strong>
"""
var html;
html = "<strong>\n cup of coffeescript\n</strong>";
二重引用符で囲まれたブロック文字列は、他の二重引用符で囲まれた文字列と同様に、補間を許可します。
生成された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構文をサポートしている必要があります。または、BabelやTraceur 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}!`;
};
ブロック文字列とコメントと同様に、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 Compiler、Babel、Rollupなどの別のトランスパイラをアタッチする必要があります。
また、import
またはexport
文を含むファイルは、トップレベル関数セーフティラッパーなしで出力されることにも注意してください。つまり、モジュールのインポートまたはエクスポートは、そのファイルに対してベアモードを自動的にトリガーします。これは、ES2015仕様では、import
またはexport
文は最上位スコープで発生する必要があるためです。
CoffeeScriptには、MakeやRakeに似た(非常に)シンプルなビルドシステムが含まれています。当然のことながら、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チュートリアルをお読みください。
本格的な用途にはお勧めしませんが、CoffeeScriptは<script type="text/coffeescript">
タグを使用してブラウザに直接含めることができます。ソースには、コンパイラの圧縮および縮小バージョンが含まれています(現在のバージョンをダウンロード、gzip圧縮時は51k)docs/v1/browser-compiler/coffee-script.js
として。このファイルをインラインCoffeeScriptタグを含むページに含めると、順番にコンパイルして評価されます。
実際、上記の「Try CoffeeScript」を実行する小さな接着剤スクリプトと、メニューのjQueryは、まさにこの方法で実装されています。ソースを表示し、ページの一番下を見て例を確認してください。スクリプトを含めると、CoffeeScript.compile()
にアクセスできるようになるため、Firebugを開いて文字列をコンパイルできます。
CoffeeScriptに関する通常の注意事項が適用されます。インラインスクリプトはクロージャラッパー内で実行されるため、グローバル変数または関数を公開する場合は、window
オブジェクトにアタッチします。
CoffeeScriptの学習を始めるのに役立つ優れたリソースがいくつかあり、その一部はオンラインで無料で入手できます。
オープンソースのCoffeeScript例は、GitHubのベストリストで見つけることができます。いくつか例を挙げると:
ソースコード
変更をテストするには`bin/coffee` を使用します。
テストスイートを実行するには`bin/cake test` を使用します。
CoffeeScriptコンパイラ全体を再構築するには`bin/cake build` を使用します。
`grammar.coffee` を編集していない場合は、`bin/cake build:except-parser` を使用するとはるかに高速に再コンパイルできます。
`git checkout lib && bin/cake build:full` は、コア言語に取り組んでいる場合に実行すると良いコマンドです。`lib`フォルダを更新し(何か壊した場合)、変更したコンパイラをビルドし、それを使用して自身を再ビルドし(健全性テスト)、すべてのテストを実行します。テストに合格すれば、変更が成功した可能性が高いです。
ブラウザテスト
現在のブラウザでCoffeeScriptのテストスイートを実行します。
CoffeeScriptの問題点
バグレポート、機能提案、言語への変更に関するアイデアは、ここに掲載してください。
CoffeeScript Google グループ
質問がある場合は、メーリングリストでサポートを受けることができます。
CoffeeScript Wiki
便利なCoffeeScriptのヒントやコツを学んだり、問題に遭遇した場合は、Wikiで共有してください。Wikiは、便利なテキストエディタ拡張機能、Webフレームワークプラグイン、および一般的なCoffeeScriptビルドツールのディレクトリとしても機能します。
FAQ
CoffeeScript関連の質問は、既に誰かが尋ねているかもしれません。最初にFAQを確認してください。
JS2Coffee
非常に優れた逆コンパイラで、JavaScriptからCoffeeScriptへの変換を行います。完璧ではありません(JavaScriptクラスを推測したり、バインド関数が必要な場合など)が、単純なスクリプトを変換するための優れた出発点となります。
高解像度ロゴ
CoffeeScriptのロゴは、プレゼンテーションで使用できるSVG形式で提供されています。
迅速なヘルプとアドバイスは、通常CoffeeScriptのIRCルームで得られます。`irc.freenode.net`の`#coffeescript`に参加するか、下のボタンをクリックしてこのページでWebチャットセッションを開きます。
CoffeeScriptは désormaisES2015の`import`および`export`構文をサポートしています。
コンパイラに`-M, --inline-map`フラグを追加しました。これにより、ソースマップを別ファイルとしてではなく、出力JavaScriptに直接埋め込むことができます。
`yield`に関する複数の修正。
`yield return`は、 désormais式として誤って使用できなくなりました。
`yield`は désormais`return`と同様に、式と共に単独で使用できます。以前`yield undefined`と書いていた箇所は、 désormais単に`yield`と書くことができます。ただし、これは`return`と同じ構文上の制限を引き継ぐことを意味するため、以下の例は désormaisコンパイルされません。
doubles = -> yield for i in [1..3] i * 2 six = -> yield 2 * 3
JavaScript出力は、不要な括弧とスペース、二重インデント、`yield`周りの二重セミコロンなどが désormais存在しないため、よりきれいに なりました。
`&&=`、`||=`、`and=`、`or=`は、 désormais等号の前にスペースを許容しなくなりました。
いくつかのエラーメッセージを改善しました。
`undefined`が`void 0`にコンパイルされるのと同様に、`NaN`は désormais`0/0`に、`Infinity`は`2e308`にコンパイルされます。
デフォルト値を持つ名前変更されたデストラクチャリングパラメータのバグ修正。`({a: b = 1}) ->`は désormaisコンパイラをクラッシュさせなくなりました。
CoffeeScriptプログラムの内部表現を改善しました。これは、`CoffeeScript.tokens`または`CoffeeScript.nodes`を使用するツールでのみ顕著です。そのようなツールは、変更または追加されたトークンとノードに対応するように更新する必要があります。
いくつかのマイナーなバグ修正を含む。
CoffeeScriptは désormaisES2015スタイルのデストラクチャリングデフォルトをサポートしています。
`(offsetHeight: height) ->`は désormaisコンパイルされません。その構文は偶然のものであり、部分的に壊れていました。代わりに`({offsetHeight: height}) ->`を使用してください。オブジェクトデストラクチャリングには常に中括弧が必要です。
いくつかのマイナーなバグ修正を含む。
$ 'body'
.click (e) ->
$ '.box'
.fadeIn 'fast'
.addClass '.active'
.css 'background', 'white'
$('body').click(function(e) {
return $('.box').fadeIn('fast').addClass('.active');
}).css('background', 'white');
--map
フラグを渡すだけで使用できます。Jason Waltonに感謝いたします。.coffee.md
もLiterate CoffeeScriptファイル拡張子としてサポートされるようになりました。.litcoffee
は標準的なものとして残ります。super
に関するいくつかの軽微な修正。for item in list by -1
registerExtension
を削除し、path.exists
からfs.exists
に移行することで、Node/コンパイラの非推奨警告を修正しました。super
をより確実に呼び出すことができるようになりました(再帰的に上へ移動します)。eval
またはarguments
の値の設定などが含まれます。#1547で完全な議論を参照してください。Ctrl-V
で複数行モードに入ります。入力を入力に直接パイプすることもできます。Generated by CoffeeScript VERSION
ヘッダーを出力するようになりました。a or= b
は、現在構文エラーと見なされます。do
のセマンティクスを調整し、名前空間をより簡単にシミュレートできるようになりました: do (x = 1, y = 2) -> …
coffee --watch
に対する追加の調整と改善。監視対象のスクリプトに構文エラーが発生した場合、監視はデフォルトでビープ音を鳴らすようになります。また、再帰的に監視する場合、デフォルトで非表示ディレクトリを無視するようになりました。coffee --watch
と--join
に対する複数の改善。これらを組み合わせて使用できるようになり、--watch
対象のフォルダ内でファイルとディレクトリを追加および削除できるようになりました。throw
文は、式の一部として使用できるようになりました。this
を持つ原因となった、より重大な1.1.3の回帰を修正しました。super
を呼び出せるようになり、バインドされたクラスメソッドは正しいコンテキストを保持するようになりました。010 is 8
と16進数0xf is 15
をサポートしていましたが、CoffeeScriptは2進数もサポートするようになりました: 0b10 is 2
require
しやすくするために、サブディレクトリの下にネストされました。たとえば、CoffeeScriptフォルダをパスに追加した後: require('coffee-script/lexer')
coffee --watch
機能は、Node.js 0.6.0以降でのみ機能するようになりましたが、Windowsでも正しく機能するようになりました。ブロックコメントのフォーマット、?=
コンパイル、制御構造に対する暗黙の呼び出し、try/catchブロックの暗黙的な呼び出し、ローカルスコープからの可変引数のリーク、heregexesに続く構文エラーの行番号、括弧で囲まれた数値リテラルのプロパティアクセス、予約名を使用したバインドされたクラスメソッドとsuper、REPLのオーバーホール、連続したコンパイル済みセミコロン、暗黙的に呼び出されたオブジェクト内のブロックコメント、およびChromeのバグに関する修正。
外部コンストラクタ関数を持つクラスのバグ修正リリース、issue #1182を参照。
coffee
実行可能ファイルを使用して実行する場合、process.argv
などはnode
ではなくcoffee
を報告するようになりました。Node.js 0.4.xモジュールのルックアップの変更との互換性が向上しました。REPLの出力がNodeのもののようにカラー化されるようになりました。--join
を使用する際に連結されたCoffeeScriptに名前を付けることが必須になりました。複合除算/=
を誤って正規表現としてレキシングする問題を修正しました。すべてのtext/coffeescript
タグは、含まれている順序で実行されるようになりました。外部コンストラクタ関数を使用する拡張サブクラスの問題を修正しました。addImplicitParentheses
の極端なケースの無限ループを修正しました。長い関数呼び出しチェーンでの指数関数的な遅延を修正しました。グローバル変数はCoffeeScript REPLにリークしなくなりました。スプラットされたパラメータは関数に対してローカルに宣言されます。
Unicode識別子に関するレキサーのバグを修正しました。Node.js 0.3.7との互換性のためにREPLを更新しました。REPLでの相対パスの要求を修正しました。末尾のreturn
とreturn undefined
は、最適化されて削除されるようになりました。Node.js 0.2.5との後方互換性のために、コアNode.js util
モジュールの要求を停止しました。条件付きreturn
がswitch
文でフォールスルーを引き起こすケースを修正しました。非構造化代入における空のオブジェクトを最適化しました。
CoffeeScriptループは、ループ本体内で関数が生成されている場合、ブロックスコープを保持しようとしないようになりました。代わりに、do
キーワードを使用して便利なクロージャラッパーを作成できます。node
実行可能ファイルに直接オプションを渡すための--nodejs
フラグを追加しました。式内の純粋なステートメントの使用に関する動作が改善されました。すべてのブラウザで-1
による包括的なスライス、およびエンドポイントとして任意の式を使用したスプライシングを修正しました。
REPLは、スタックトレースを適切にフォーマットし、非同期例外の間もアクティブな状態を維持するようになりました。--watch
を使用すると、ファイルがコンパイルされるときにタイムスタンプが出力されるようになりました。摘出されたクロージャループ内で誤ってリークしていた変数を修正しました。コンストラクタは、クラス本体内の宣言位置を維持するようになりました。動的なオブジェクトキーは削除されました。ネストされたクラスがサポートされるようになりました。裸のスプラットされた関数の実行コンテキストを修正しました。チェーンされた比較の反転のバグを修正しました。チェーンされたクラスのインスタンス化は、スプラットで適切に機能するようになりました。
0.9.5は、CoffeeScript 1.0の最初のリリース候補と見なすことができます。以前のリリース以降、内部的な変更が多数行われており、その多くはsatyrのCoffeeScriptの方言であるCocoから貢献されています。Heregex(拡張正規表現)が追加されました。関数は、デフォルトの引数を指定できるようになりました。クラス本体は、実行可能なコードになりました。無効なCoffeeScriptに対する構文エラーが改善されました。undefined
はnull
のように動作するようになり、新しい値を代入できなくなりました。単一行のリスト内包表記に関して優先順位の変更がありました: result = i for i in list
は、デフォルトでresult = (i for i in list)
として解析されていましたが…現在は(result = i) for i in list
として解析されます。
CoffeeScriptは、適切に名前付けされた一時変数を使用し、使用後に参照をリサイクルするようになりました。Node.js 0.3のrequire.extensions
サポートを追加しました。ブラウザでCoffeeScriptを読み込むと、グローバルスコープに単一のCoffeeScript
オブジェクトが追加されるようになりました。暗黙的なオブジェクトとブロックコメントの極端なケースの修正。
CoffeeScriptのswitch
文は、JSのswitch
文にコンパイルされるようになりました。以前はJavaScript 1.3との互換性のためにif/else
チェーンにコンパイルされていました。関数の呼び出しのソーキングがサポートされるようになりました。RubyMineエディタのユーザーは、--watch
モードを使用できるようになりました。
範囲リテラルの開始と終了の指定はオプションになりました(例: array[3..]
)。a not instanceof b
と言うことができます。ネストされた重要なインデントと重要ではないインデントに関する重要なバグを修正しました(Issue #637)。coffee
コマンドにフックできる--require
フラグを追加しました。優先するJavaScriptLint設定のためのカスタムjsl.conf
ファイルを追加しました。演算のルールをフラット化することで、Jison文法のコンパイル時間を短縮しました。ブロックコメントは、JavaScript縮小ツールに優しい構文で使用できるようになりました。JavaScriptの複合代入ビット演算子を追加しました。暗黙的なオブジェクトリテラルの先頭に数値キーと文字列キーがある場合、暗黙の呼び出しの対象として、および複合代入の一部として、バグを修正しました。
0.9.1のバグ修正リリースです。混合された暗黙的なオブジェクト、暗黙的な関数呼び出し、および暗黙的なインデントの処理が大幅に向上しました。文字列と正規表現の補間は、厳密に#{ … }
(Rubyスタイル)になりました。コンパイラは、コンパイル前に実行するスクリプトを指定する--require
フラグを受け取るようになりました。
CoffeeScript 0.9 シリーズは、1.0 のリリース候補とみなされています。徹底的なテストを行いましょう。0.9.0 では、後方互換性のない大きな変更が導入されました。代入には =
を、オブジェクトリテラルには :
を使用するようになりました(JavaScript と同じです)。これにより、暗黙的なオブジェクトリテラルと YAML スタイルのオブジェクト定義が可能になります。+=
、or=
などに置き換え、ハーフアサインメントは削除されました。補間はドル記号 $
の代わりにハッシュマーク #
を使用するようになりました — ドル記号は有効な JS の識別子の部分になる可能性があるためです。下向き範囲内包表記が再び安全になり、整数端点で作成された場合は、通常の for ループに最適化されます。高速でガードのないオブジェクト内包表記の形式が追加されました: for all key, value of object
。引数なしで super
キーワードを指定すると、Ruby と同様に、関数に渡されたすべての引数が転送されるようになりました。親クラス A
からクラス B
を拡張する場合、A
に extended
メソッドが定義されていると、B
を渡して呼び出されます — これにより、静的継承などが可能になります。太い矢印でバインドされた関数の出力がきれいになりました。@variables
をパラメータリストで使用できるようになりました。パラメータはオブジェクトのプロパティとして自動的に設定されます — コンストラクタとセッター関数で役立ちます。コンストラクタ関数は、スプラットを受け取ることができるようになりました。
coffee
コマンドラインオプションが特定の状況で解析されない問題に対する迅速なバグ修正(0.7.1 の直後)。
ブロックスタイルのコメントがそのまま渡され、JavaScript のブロックコメントとして出力されるようになりました。ライセンスや著作権ヘッダーに役立ちます。ハッシュバングを使用した CoffeeScript のスタンドアロン実行のサポートが向上しました。文法にないトークンに対する構文エラーが改善されました。
CoffeeScript の公式変数スタイルは、JavaScript と同様に camelCase になりました。予約語をオブジェクトキーとして使用できるようになり、自動的に引用符で囲まれます。範囲内包表記はよりクリーンなコードを生成するようになりましたが、下向きに反復処理するには by -1
を指定する必要があります。構文エラーのレポートが前のリリースから大幅に改善されました。引数なしで coffee
を実行すると、Readline サポート付きの REPL が起動します。<-
バインド演算子は CoffeeScript から削除されました。while true
ループに相当する loop
キーワードが追加されました。クロージャを含む内包表記は、forEach
のセマンティクスのように、その変数を閉じ込めます。クラス定義内でバインド関数を(インスタンスにバインドして)使用できるようになりました。一貫性のため、a in b
は配列の存在チェックになり、a of b
はオブジェクトキーチェックになりました。コメントは生成された JavaScript に渡されなくなりました。
coffee
コマンドは、スクリプトのディレクトリ全体をコンパイルする際、ディレクトリ構造を保持するようになりました。CoffeeScript コンパイラが Internet Explorer 内でライブ実行されないのを防いでいた 2 つの欠落を修正しました。CoffeeScript の heredoc と同様のブロックコメントの構文が追加されました。プロパティの名前と値の名前が同じである ECMA Harmony DRY スタイルのパターンマッチングがサポートされるようになりました: {name, length}: func
。内包表記変数内でパターンマッチングが許可されるようになりました。ブロック形式で unless
が許可されるようになりました。while
ループの逆として until
ループが追加されました。スイッチオブジェクト節なしで switch
文が許可されるようになりました。Node.js v0.1.95 と互換性があります。
新しい Node.js v0.1.90 シリーズとの互換性のために CoffeeScript がアップグレードされました。
Python のように、末尾のカンマが許可されるようになりました。@property
表記を使用して、クラス定義内で静的プロパティを直接代入できるようになりました。
補間を正規表現、heredoc、文字列内で使用できるようになりました。<-
バインド演算子が追加されました。特別な ||=
スタイルの演算子の代わりに、ハーフ式への代入を許可しました。引数オブジェクトは、配列に自動変換されなくなりました。coffee-script
を require した後、registerExtension のおかげで、Node.js は .coffee
ファイルを直接ロードできるようになりました。関数呼び出し、配列、パターンマッチングで複数のスプラットを使用できるようになりました。
Stan Angeloff 氏による文字列補間の寄稿。0.5.3 以降、--run
がデフォルトになっているため、--stdio
と --eval
もデフォルトで実行されるように更新されました。結果を出力したい場合は、--compile
も渡してください。
Node.js のグローバル定数 __filename
と __dirname
を修正するバグ修正。ネストされた関数リテラルとインデントが不適切なコメントのより柔軟な解析のための調整。最新の Node.js API への更新。
CoffeeScript にクラス定義の構文が追加されました。コアコンポーネント(ノード、字句解析器、書き換え器、スコープ、Optparse)の多くがそれらを使用しています。Cakefile は optparse.coffee
を使用して、タスクのオプションを定義できます。coffee
コマンドのデフォルトフラグは --run
になり、JavaScript を保存するには --compile
を使用します。正規表現リテラルと連結除算のあいまいさに関するバグ修正。
ウェブページに含めるためのコンパイラの圧縮版(browser-compiler/coffee-script.js
)が追加されました。タイプが text/coffeescript
のスクリプトタグを自動的に実行します。パイプで入力されたコンパイル用の --stdio
オプションが coffee
コマンドに追加されました。
存在演算子を使用した null ソーキングの改善(インデックス付きプロパティのソーキングを含む)。while
ループに条件が追加され、内包表記と同様に when
を使用してフィルタとして使用できるようになりました。
CoffeeScript 0.5.0 はメジャーリリースです。言語の変更はありませんが、Ruby コンパイラが削除され、純粋な CoffeeScript で記述されたセルフホスティングコンパイラに置き換えられました。
@property
は this.property
の省略形になりました。デフォルトの JavaScript エンジンが Narwhal から Node.js に変更されました。引き続き Narwhal を使用したい場合は、--narwhal
フラグを渡してください。
CoffeeScript 0.3 には、主要な構文の変更が含まれています。関数記号が ->
に変更され、バインド関数の記号は =>
になりました。関数定義のパラメータリストは、括弧で囲む必要があります。?.
演算子を使用してプロパティソーキングが追加されました。引数付きの関数を呼び出す場合、括弧を省略可能にしました。廃止されたブロックリテラル構文を削除しました。
Python スタイルの連結比較、条件付き存在演算子 ?=
、および *Beautiful Code* からのいくつかの例を追加しました。ステートメントから式への変換、引数から配列への変換、および TextMate 構文ハイライターに関するバグ修正。
switch 文の条件で複数の値を一度に指定できるようになりました — それらのいずれかが true の場合、そのケースが実行されます。this
に関数を定義してすぐにバインドする長い矢印 ==>
を追加しました。内包表記と同様に、while ループを式として使用できるようになりました。パターンマッチ内でスプラットを使用して、配列の残りを吸収できます。
ネストされた配列とオブジェクトから値を抽出するための、ECMAScript Harmony スタイルのデストラクチャリング代入を追加しました。インデントに依存する heredoc を追加し、きれいにフォーマットされた文字列やコードチャンクを作成します。
不十分な ino
キーワードを削除し、オブジェクト内包表記に of
を使用して置き換えられました。これにより、次のように記述できるようになりました: for prop, value of object
。
オブジェクトを対象とした内包表記を実行する際には、コンパイル時により小さく、効率的なコードを生成するために、in
の代わりに ino
を使用します。.prototype.
の省略形として ::
を追加しました。「スプラット」記号は、プレフィックスのアスタリスク *
から、ポストフィックスの省略記号 ...
に変更されました。JavaScript の in
演算子、空の return
文、空の while
ループを追加しました。大文字で始まるコンストラクタ関数は、オブジェクトの新しいインスタンスが返されることを確認するための安全チェックを含みます。extends
キーワードは、Google の Closure Library の goog.inherits
と同じように機能するようになりました。
参照されたときに、引数オブジェクトが実際の配列に変換されるようになりました。
メジャーリリース。重要な空白処理。ステートメントから式への変換の改善。スプラット。スプライスリテラル。オブジェクト内包表記。ブロック。存在演算子。問題を投稿してくれた皆さんに感謝します。Liam O’Connor-Davis 氏には、空白処理と式のヘルプに関して特に感謝しています。
CoffeeScriptディレクトリ外から`coffee --interactive`および`--run`を実行する際のバグ修正。ネストされた関数/if文のバグ修正。
配列スライスリテラルと配列内包表記は、開始と終了を指定するためにRubyスタイルの範囲を使用できるようになりました。JavaScriptの変数宣言はスコープの先頭に移動されるようになり、すべての代入文が式になります。`\`を使用して改行をエスケープできます。`coffee-script`コマンドは`coffee`に変更されました。
公式のCoffeeScript拡張子は、C#に適切に属する` .cs`ではなく` .coffee`になりました。多くの要望に応え、`=`を使用して代入することもできるようになりました。JavaScriptとは異なり、`=`はオブジェクトリテラル内でも`:`と置き換え可能に使用できます。`func(1)(2)(3)(4)`のような連鎖した関数呼び出しの文法的な修正を行いました。継承とsuperは`__proto__`を使用しなくなったため、IEと互換性があるはずです。
`coffee`コマンドに`--interactive`が追加されました。これは対話型のCoffeeScriptセッションを起動します。また、`--run`はスクリプトを直接コンパイルして実行します。両方のオプションは、Narwhalの動作するインストールに依存します。`aint`キーワードは`isnt`に置き換えられました。これは`is`とよりスムーズに連携します。引用符で囲まれた文字列は、オブジェクトリテラル内で識別子として許可されるようになりました(例:`{"5+5": 10}`)。すべての代入演算子はコロンを使用するようになりました:`+:`, `-:`, `*:`, など。
`extends`キーワードの再追加により、複数のレベルの継承を通して`super()`を呼び出す際のバグを修正しました。実験的なNarwhalサポート(Tuskパッケージとして)を追加しました(Tom Robinson提供)。これには、CoffeeScript REPLおよびインタープリターとしての**bin/cs**が含まれます。安全な関数ラッパーを抑制するための新しい`--no-wrap`オプション。
`instanceof`と`typeof`を演算子として追加しました。
CoffeeScriptの最初のリリース。