インフィニットループ 技術ブログ

2011年03月30日 (水)

著者 : tek_koc

CoffeeScript基礎文法最速マスター

はじめまして。新人のtek_kocです。
今回は巷で話題のCoffeeScriptの文法をまとめてみました。
1年近く前に流行った基礎文法マスターシリーズにCoffeeScriptがなかったので、勉強も兼ねて同形式で書いてます 。
JavaScriptを使っている方はこれをざっくり眺めてCoffeeScriptへの移行を検討してくれればなと思います。
まだ網羅しきれていないですが、これを読めばCoffeeScriptに乗り換えることができるはずです。
間違いや、足りない箇所などがあれば、是非コメント等で指摘してください!

バージョン

現時点で最新の1.0.1を対象にします。

0.概要

CoffeeScriptとはJavaSciprtにコンパイル可能な言語です。
RubyやPythonなどに近い記述が可能で、JavaScriptの開発をより効率的にできます。特にTitanium mobileを使ってJavaScriptでスマートフォン開発をしている方や、node.jsを使っている方にお勧めです。もちろん、クライアントスクリプトとしてのJavaScriptで使うのもアリです。
インストールはnode.jsのパッケージマネージャのnpmからできます。インストールの詳しい方法は「CoffeeScript インストール」でまとまっているので、そちらを参考にしてください。
ちょっと試したいだけならCoffeeScriptの公式サイト上で簡単に試すこともできます。

1.基礎

print文

console.log "Hello World!"

JavaScriptの場合と同じく、console.logを使います。JavaScriptにコンパイルするだけなので、同じなのは当然といえば当然ですね。ブラウザの場合はalertなどを使ってもいいと思います。

コメント

# 一行コメント
###
複数行コメント
###

一行コメントはコンパイル時に消えます。複数行コメントはコンパイル後にも残ります。

変数の宣言

age = 22
name = "tek_koc"

JavaScriptの場合と異なり、varは付けません。コンパイル時にスクリプトの先頭で自動でvar付きで変数宣言されます。

行末のセミコロンについて

JavaScriptでは行末のセミコロンは省略可能ですが省略非推奨でした。CoffeeScirptはこれまでの例の通り、行末のセミコロンは必要ありません。

スクリプトの実行

スクリプトをtest.coffeeとして保存したとして場合は、以下のコマンドで実行できます。

$ coffee test.coffee 

スクリプトのコンパイル

CoffeeScriptが真価を発揮するのはJavaScriptにコンパイルした場合です。

$ coffee -c test.coffee

例えば、以下のCoffeeScriptをJavaScriptにコンパイルしてみます。
CoffeeScript

for i in [1..100]
     str = if i % 3 is 0 and i % 5 is 0
          "fizzbuzz"
     else if i % 3 is 0
          "fizz"
     else if i % 5 is 0
          "buzz"
     else
          i
     console.log str

JavaScript

(function() {
  var i, str;
  for (i = 1; i <= 100; i++) {
    str = i % 3 === 0 && i % 5 === 0 ? "fizzbuzz" : i % 3 === 0 ? "fizz" : i % 5 === 0 ? "buzz" : i;
    console.log(str);
  }
}).call(this);

もし、全体を無名関数で括る必要がない場合は、オプションで指定できます。

$ coffee -cb test.coffee

2.数値

数値表現

JavaScriptと同じで、内部的には全て実数として扱われます。

n = 123
f = 1.23
h = 0xff # 16進数
o = 077 # 8進数

四則演算

JavaScriptと同じです。

a = 1 + 1
b = 2 - 1
c = 3 * 2
d = 4 / 2
a++
b--

3.文字列

文字列表現

hello = "world"

式展開

式展開ができます。これは便利ですね。文字列をシングルクオーテーションで括った場合は、式展開されないです。

name = "tek_koc"
str = "I am #{name}"    # "I am tek_koc"

ヒアドキュメント

”’で括ることで、ヒアドキュメントも使えます。

html = '''
hoge
<ul>
	<li>a</li>
	<li>b</li>
	<li>c</li>
</ul>
'''
console.log html

先頭のインデントはちゃんと削除されます。

文字列操作

特にJavaScriptと変わりません

join = "tek" + "_" + "koc"          # "tek_koc"
record = "tek_koc".split "_"          # ["tek", "koc"]
length = "tek_koc".length          # 7

4.配列

JavaScriptよりもパワフルになってます。

生成

JavaScriptと同じく、[]で生成します。

numAry = [1, 1, 2, 3, 5, 8]
strAry = [
     "a"
     "b"
     "c"
]

通常はコンマで区切りますが、改行文字も区切り文字になります。

範囲記法

いわゆるRangeが使えます。

ary = [1..10]
ary2 = [1...10]

aryは1から10。ary2は1から9までの数値配列になります。

for式による生成

for式についてはあとで詳しく書きますが、for式でも配列を生成できます。

ary = for i in [0...10] then i * i

これで、[ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ]を作れます。

配列内包表記

配列内法表記も使えます。上を配列内包表記に置き換えると、次のようになります。

ary = (i * i for i in [0...10]) 

配列の参照と代入

参照についてはJavaScriptと同じです。

ary = [0..10]
console.log ary[2] # 2

代入も同じですが、範囲指定置換というものも使えます。

ary = [0..10]
ary[0] = 10
ary[3..5] = [5..3]
console.log ary

結果は、[ 10, 1, 2, 5, 4, 3, 6, 7, 8, 9, 10 ] です。

5.オブジェクト(連想配列)

オブジェクトのプロパティのアクセスを、いわゆる連想配列のように書けます。JavaScriptでもおなじみですね。

obj = {name:"tek_koc", age:"22"}
hash = []
hash["name"] = "tek_koc"
hash["age"] = 22
console.log obj["name"]     # "tek_koc"
console.log hash.age     # 22

オブジェクトの生成

obj = {
     x:100
     y:150
}

配列と同じで、改行文字を,区切り文字として使えます。  YAMLのように書くこともできます。

obj =
     name:"tek_koc"
     age:22
     blother:
          name:"himitsu"
          age:6

結果は、以下のとおりです。

{ name: 'tek_koc',
  age: 22,
  blother: { name: 'himitsu', age: 6 } }

6.制御文

CoffeeScriptはできるだけすべての文を式として扱えるようにしています。  また、pythonと同じくインデントでブロックを表現します。

if式

JavaScriptとほぼ同じですが、値を返すという点が大きく違います。  それと、unlessも使えます。ifの反対です。

value = 3
if value is 3
    console.log "3だよ。"
else
    console.log "3じゃないよ。"
result = unless value isnt 4
    "4だよ。"
else
    "4じゃないよ。"
console.log result 

条件式は()で括りません。また、{}でブロックを囲いません。

条件演算子

制御文の解説を続ける前に、制御文に欠かせない条件演算子について触れておきます。

JavaScript CoffeeScript
=== is
!== isnt
! not
&& and
|| or
true true,yes,on
false false,no,off

記号の代わりに英語になることで、より意味が明瞭になるので個人的には好きです。

一行if式

一行でif式を書く場合には、条件部との区切りにthenを使います。

flg = true
console.log if flg then "正" else "否"

後置if

後置のifも使えます。

flg = off
console.log "正" if flg
console.log "否" unless flg

繰り返し

whileやuntilを使います。whileは条件を満たしているときに処理を繰り返し、untilは条件を満たすまで処理を繰り返します。また、ifと同じく後置して使うこともできますし、値も配列として返します。

i = 0
while i < 5
     console.log i
     i++
# 1 2 3 4
i = 0
ary = until i is 5 then i++
console.log ary
# [0, 1, 2, 3, 4]

for式

配列やオブジェクトのループに使います。範囲記法を使うことで、JavaScriptのfor文のような書き方もできます。

ary = [
     "abc"
     "def"
     "ghi"
     "jkl"
]
for value in ary
     console.log value
kuku = for i in [1..9]
          for j in [1..9]
               i * j
console.log kuku

オブジェクトのループにはinではなく、ofを使います。JavaScriptのinに近い挙動です。

obj =
     name:"tek_koc"
     age:22
     blother:
          name:"himitsu"
          age:6
for key of obj
     console.log "#{key}:#{obj[key]}"

実行結果

name:tek_koc
age:22
blother:[object Object]

7.関数

関数の定義・呼び出し

JavaScriptでは次のように関数を定義します。

function hello() {
    console.log("hello");
}

一方で、無名関数を用いて、変数に代入することで関数を定義することもできます。

var hello = function() {
    console.log("hello");
};

CoffeeScriptの関数定義は、基本的に後者の無名関数を使う方法でやります。

hello = -> console.log "hello" 

->を使って関数の定義を行います。「-> console.log “hello”」の部分が無名関数です。  hello変数に無名関数を代入することで、hello関数として実行出来るようにしています。  呼び出す場合は()を付けます。

hello()

()を付けない場合は、関数そのものを表します。例えば引数として関数を渡す場合、()の有無は、関数を指定するか、関数の実行結果を指定するかの違いになります。  無名関数を代入して新規の関数を定義するだけではなく、既存の関数を代入することもできます。

print = console.log
print "Hello World!"

よく使う関数はこのように簡単にかけるようにするのもアリです。ただし、名前空間を汚すことになるので注意は必要です。

戻り値について

関数の戻り値は関数の最後に評価された式の結果になります。  明示的にreturnで指定することもできます。

引数付きの関数定義・呼び出し

引数を指定する場合は、次のように書きます。

add = (n, m) -> n + m

呼び出す場合は()の中に関数に渡したい値を書きます。

add(3, 5)    # 8

先ほどから、console.logの呼び出しにカッコを省略していたように、引数を渡す関数の場合、カッコを省略できます。  例えば「add(3, 5)」は「add 3, 5」と書けます。  console.logで出力もする場合は、次のようになります。

add = (n, m) -> n + m
console.log add 3, 5>---# 8

オブジェクトを引数にとる関数

オブジェクトを渡すときは、オブジェクトの{}を省略できます。

print = console.log
disp = (obj) -> "(#{obj.x}, #{obj.y})"
print disp({x:10, y:20})
print disp(x:10, y:20)
print disp x:10, y:20

すべて同じ実行結果です。

デフォルト引数と可変引数

デフォルト引数や可変引数なども利用可能です。

func = (str = "hoge") -> "Hello #{str}!"
console.log func() # Hello hoge!
prints = (ary...) -> for i in ary then console.log i
prints "abc", "def", "ghi"
# abc
# def
# ghi

高階関数の呼び出し

setTimeoutのように、関数を指定する関数を書く場合は次のようにします。

setTimeout ->
     console.log "ok"
, 1000

無名関数の次の引数を書くときに、行の先頭にコンマを付けます。

高階関数の定義

関数を受け取る関数を作ることもできます。JavaScriptと比べて関数リテラルが簡潔なので、新しい制御文を自分で作るかのようにプログラムすることができます。  あまりいい例では無い気がしますが、次のような関数を作れます。渡された配列に、関数を適用する関数です。

foreach = (ary, f) ->
     for i in ary
          f(i)
foreach [1..10], (v) ->
     console.log v * v

8.その他のTips

存在演算子

JavaScriptで厄介な存在チェックですが、存在演算子「?」を付けることで簡単にできます。

foo = "hoge"
console.log foo if foo?          # hoge
console.log bar if bar?          # 未定義変数でもエラーがでない

プロパティチェーンでも使えます。便利。

obj =
     name:"tek_koc"
     age:22
     brother:
          name:"himitsu"
          age:6
console.log obj.brother.name if obj.brother?.name?
console.log obj.sister.name if obj.sister?.name?

JavaScriptの実行

推奨はされないですが、JavaScriptを埋め込むこともできます。

`var func = function(str) {console.log(str);};`
funct "test"    # test

ブログ記事検索

このブログについて

このブログは、札幌市・仙台市の「株式会社インフィニットループ」が運営する技術ブログです。 お仕事で使えるITネタを社員たちが発信します!