CoffeeScriptの文法について理解していないとこが多かったので、自分の覚書もふくめまとめてみました。
基本
- CoffeeScriptはJavaSciprtにコンパイル可能な言語
- CoffeeScriptはインデントでブロックを表現する
- 行末の;(セミコロン)は不要
- 数値表現、四則演算はjavascriptと同様
コンパイル
$ coffee -c hoge.coffee
例えば
hoge = "hogehoge" console.log hoge
は以下のようなjavascriptにコンパイルされます
(function() { var hoge; hoge = "hogehoge"; console.log(hoge); }).call(this);
無名関数で括りたくない場合は
$ coffee -cb hoge.coffee
とします。
ログ出力
console.log "hoge"
出力
hoge
コメント
#でコメントアウトされます
#コメントです
複数行の場合は#3つで囲む
### コメントです hogehoge fugafuga ###
変数
javascriptでは変数宣言の前にvarを置かないかぎりグローバル変数として宣言したことになる CoffeeScriptでは自動的に全ての変数宣言にvarがつけられる
CoffeeScript
hoge = "hoge"
javascript
var hoge; hoge = "hoge";
文字列
hoge = "hoge" fuga = 'fuga'
ダブルクォテーションの場合#{変数名}で変数が展開されます
fuga ="fuga" hoge = "hoge#{fuga}" console.log hoge
出力
hogefuga
シングルクォテーションの場合は展開されません
fuga ='fuga' hoge = 'hoge#{fuga}' console.log hoge
出力
hoge#{fuga}
文字列の操作
hoge = "hoge" fuga = "fuga" console.log hoge + fuga
出力
hogefuga
ヒアドキュメント
"""ダブルクォテーション3つで囲むと複数行の文字列を扱える #{変数名}で変数が展開される
name ="bokuweb" text =""" hogehoge fugafuga #{name} """ console.log text
出力
hogehoge fugafuga bokuweb
'''シングルクォテーション3つで囲むと変数は展開されない
name ="bokuweb" text =''' hogehoge fugafuga #{name} ''' console.log text
出力
hogehoge fugafuga #{name}
エイリアス
@はthisのエイリアス
@hoge = "hoge" # this.hoge = "hoge"と同じ
::はprototypeのエイリアス
hoge::fuga = -> console.log "hoge" # hoge.prototype.fuga = と同じ
演算子
演算子のエイリアス
JavaScript | CoffeeScript |
---|---|
=== | is |
!== | isnt |
! | not |
&& | and |
|| | or |
true | true,yes,on |
false | false,no,off |
of | in |
** | Math.pow(a,b) |
// | Math.floor(a / b) |
%% | (a % b + b) % b |
比較演算子の連結
こういった表現ができます。
if a > b > c then console.log "hoge"
存在演算子
存在演算子「?」を使うと、値がnullやundefined以外の時は true を返す javascriptより変数に値が入っているか簡単に調べられる
hoge = null if hoge? # true console.log fuga
3項演算子
CoffeeScriptでは?は存在演算子に使用されているためif ~ then ~ elseで代用
a = if b then 1 else 2
if文
1行if
条件部との区切りにthenを使う
if hoge then console.log "hoge"
後置if
hoge = 5 console.log "hoge" if hoge is 5 # hogeと出力される
unless
unless false console.log "hoge" # hogeと出力される
swith文
CoffeeScriptではcase、defaultではなく、whenとelseで書きます。
switch val when 1 console.log "1" when 2 then console.log "2" when 3,4,5 console.log "3,4,5" else console.log "else"
配列
配列はインデントをカンマの代わりに区切に用いることができる。 ただし角括弧([])は必須。
array1 = [1, 2, 3] array2 = [ 1 2 3 ]
range
最初と最後の位置を示す2つの数値は..か...で区切られる。
array1 = [1..10] # array1は1から10 array2 = [1...10] # array2は1から9
もし範囲が変数の直後に置かれたならCoffeeScriptはそれをslice()メソッドの呼出に変換する 以下の場合元の配列の最初の2つの要素のみを持つ配列を返す
firstTwo = ["one", "two", "three"][0..1]
オブジェクト
object1 = {one: 1, two 2} # 中括弧省略 object2 = one: 1, two: 2 # 改行をカンマの変わりにする object3 = one: 1 two: 2
for文
配列のループ
for i in [0..9] console.log i ### 出力 0 1 2 3 4 5 6 7 8 9 10 ###
要素をスキップして繰り返す
for i in [0..10] by 2 console.log i ### 出力 0 2 4 6 8 10 ###
配列を逆からループ
array = [0, 2, 4, 9] for v, i in array by -1 console.log "i = " + i + " v = " + v ### 出力 i = 3 v = 9 i = 2 v = 4 i = 1 v = 2 i = 0 v = 0
array = [ 'one' 'two' 'three' ] for i in [0...array.length] console.log array[i] ### 出力 one two three ###
array = [ 'one' 'two' 'three' ] for value in array console.log value ###出力 one two three ###
繰り返しのインデックスがいる場合
array = [ 'one' 'two' 'three' ] for value,i in array console.log "i=" + i + ",value = " + value ### 出力 i=0,value = one i=1,value = two i=2,value = three ###
forも1行でかける
for i in [0..9] then console.log i
もしくは
console.log i for i in [0..9]
これは
array = for i in [0...10] then i * i
このようにもかける
array = (i * i for i in [0...10])
フィルタリングもできる この場合値が3未満の要素を含む配列を返す
array = [0, 1, 2, 3, 4, 5] array2 = for value in array when value < 3 then value console.log array2 ### 出力 [0, 1, 2] ###
オブジェクトのループ
オブジェクトの場合「in」ではなく「of」を使う
obj = 'one' : 1 'two' : 2 'three' : 3 for key,value of obj console.log "key=" + key + ",value = " + value 出力 key=one,value = 1 key=two,value = 2 key=three,value = 3 ###
while文
count = 0 while count < 15 count++ console.log count #15
後置whileも使える
count = 10 console.log "count = #{count}" while count-- ### 出力 count = 9 count = 8 count = 7 count = 6 count = 5 count = 4 count = 3 count = 2 count = 1 count = 0 ###
until文
count = 0 count++ until count >= 10 console.log count #10
loop文
while trueと同じ
count = 0 loop if ++count >= 15 then break console.log count #15
関数
返り値を持った関数
返値は最後に処理した値になる。(関数の最後の行とは限らない。)
func = -> sum = 1 + 1
返り値なし
値を返したくない場合じゃ明示的にreturnを付ける
func = -> sum = 1 + 1 return
引数を持つ場合
func = (arg1,arg2)-> sum = arg1 + arg2
デフォルト引数
func = (arg1 = 1,arg2 = 5)-> sum = arg1 + arg2
無名関数の即時実行
do-> sum = 1 + 1
引数を持つ無名関数の即時実行
do(num)-> num + 1
可変長引数
func = (x,args...)-> console.log args
関数コンテキスト
以下のようにした場合、2行目の@すなわちthisはelementに等しくなる。 それにより以下のコードは期待した動作にならない。
@clickHandler = -> alert "clicked" element.addEventListener "click", (e) -> @clickHandler(e)
CoffeeScriptでは->の代わりに=>(ファットアロー)を使用することでthisをローカルコンテキストにバインドできるようです。
@clickHandler = -> alert "clicked" element.addEventListener "click", (e) => @clickHandler(e)
上記のものをコンパイルすると以下のようなjavascriptが生成されます。
(function() { var _this = this; // thisをバインド this.clickHandler = function() { return alert("clicked"); }; element.addEventListener("click", function(e) { return _this.clickHandler(e); // thisではなく_thisを使用 }); }).call(this);
クラス
クラスの宣言
class Hoge
インスタンスの作成
クラスのインスタンスはnew演算子を用いて作成する
fuga = new Hoge
コンストラクタの定義
インスタンス化時にconstructorが実行されます
class Hoge fuga : "fuga" constructor: (name) -> @name = name
クラスの拡張
extendsキーワードでクラスの拡張が可能
class Fuga extends Hoge
super
スーパークラスの関数をsuper()で呼ぶことができる
class Hoge constructor: (name) -> @name = name class Fuga extends Hoge constructor: -> super("Fuga")
private変数/関数
以下のようにすればよいらしい
class Hoge private1 = 1 private2 = -> console.log "hoge"
別ファイルのクラスを参照
別ファイルのクラスを参照しようと思ってもCoffeeScriptのコンパイル時に無名関数でラッピングされてしまい別ファイルからクラスが見えなくなる。 例えば
class Hoge
はコンパイルすると以下のようになる
(function() { var Hoge; Hoge = (function() { function Hoge() {} return Hoge; })(); }).call(this);
これにより別ファイルからHogeは見えなくなる。
対策としてclass名に@をつければいいっぽい これによりクラス名がグローバルなスコープに追加される
class @Hoge
正規表現
javascriptと同様ですが、///で囲むことで複数行にわたってパターンを記述できる。
以下のページがわかりやすい javascript入門/正規表現編
OPERATOR = /// ^ ( ?: [-=]> # function | [-+*/%<>&|^!?=]= # compound assign / compare | >>>=? # zero-fill right shift | ([-+:])\1 # doubles | ([&|<>])\2=? # logic / shift | \?\. # soak access | \.{2,3} # range or splat ) ///
コンパイル後
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
javascriptの挿入
バッククォーテーションでくくった部分はJavaScriptとして挿入される
`
var hoge;
console.log(hoge);
`
参考記事
- http://verytired.hateblo.jp/entry/2012/12/18/210223
- http://www.infiniteloop.co.jp/blog/2011/03/coffeescript-master/
- http://blog.codebook-10000.com/entry/20140112/1389526832
- http://yokotakenji.me/log/programming/js/coffeescript/2217/
- http://memo.sappari.org/coffeescript/coffeescript-langref
- http://d.hatena.ne.jp/nodamushi/20110108/1294518316
- http://minghai.github.io/library/coffeescript/index.html