CoffeeScript


##2. 概要

コメント書き方

```CoffeeScript
# comment
###
comment
comment
###
```

1.変数にvarをつけない
2.;は不要
3.{}はインデントで表現
4.()は曖昧性がない場合、省略可能

例

```CoffeeScript
score = 82
if score > 80
  alert "OK"
###
```

```JavaScript
var score;

score = 82;

if (score > 80) {
  alert("OK");
}
```

5.JavaScriptを使いたい場合バッククォートで囲む

例

```CoffeeScript
`alert("hello");`
###
```

```JavaScript
alert("hello");;
```

##3. 文字列

式展開はダブルクウォーテで囲む

```CoffeeScript
score = 80
alert "score: #{score}"
alert "score: #{score * 10}"
```

```JavaScript
var score;

score = 80;

alert("score: " + score);

alert("score: " + (score * 10));
```

文字列中の改行はスペースに変換される

```CoffeeScript
msg = "this
is
a very
long
msg
"
```

```JavaScript
var msg;

msg = "this is a very long msg";
```

heredoc(インデントや改行を保持したまま文字列をコード中に埋め込む)

```CoffeeScript
html = """
       <div id="main">
         hello
       </div>
       """
```

```JavaScript
var html;

html = "<div id=\"main\">\n  hello\n</div>";
```

##4. 配列

配列は改行を使うこともできる(インデントは必要)

```CoffeeScript
a = [
 1
 3
 5
]
```

```JavaScript
var a;

a = [1, 3, 5];
```

連番記号

```CoffeeScript
m = [0..5]
```

```JavaScript
var m;

m = [0, 1, 2, 3, 4, 5];
```

連番記号(最後の数字は含まない)

```CoffeeScript
m = [0...5]
```

```JavaScript
var m;

m = [0, 1, 2, 3, 4];
```

配列の取り出し

```CoffeeScript
m = [0..5]

alert m[1..3]
```

```JavaScript
var m;

m = [0, 1, 2, 3, 4, 5];

alert(m.slice(1, 4));
```

配列の取り出し(補足)

```CoffeeScript
m = [0..5]

alert m[..3]
alert m[1..]
alert m[..]
alert m[1..-2]
```

```JavaScript
var m;

m = [0, 1, 2, 3, 4, 5];

alert(m.slice(0, 4));

alert(m.slice(1));

alert(m.slice(0));

alert(m.slice(1, -1));
```

配列の入れ替え

```CoffeeScript
m = [0..5]

m[0..1] = ["a","b","c"]
alert m
```

```JavaScript
var m, ref;

m = [0, 1, 2, 3, 4, 5];

[].splice.apply(m, [0, 2].concat(ref = ["a", "b", "c"])), ref;

alert(m);
```

配列の入れ替え(文字列)

```CoffeeScript
alert "world"[1..3]
```

```JavaScript
alert("world".slice(1, 4));
```

##5. オブジェクト

オブジェクトの書き方

```CoffeeScript
m = name: "tagudhi", score: 80
```

```JavaScript
var m;

m = {
  name: "tagudhi",
  score: 80
};
```

オブジェクトの書き方(YMLのような形式で書くこともできる)

```CoffeeScript
m = 
　name: "tagudhi"
　score: 80
```

```JavaScript
var m;

m = {
  name: "tagudhi",
  score: 80
};
```

オブジェクトの書き方(入れ子)

```CoffeeScript
m = 
　name: "tagudhi"
　score:
    first: 80
    second: 70
    third: 90
```

```JavaScript
var m;

m = {
  name: "tagudhi",
  score: {
    first: 80,
    second: 70,
    third: 90
  }
};
```

##6. if

ifで条件分岐

```CoffeeScript
if score > 60
  alert score
```

```JavaScript
if (score > 60) {
  alert(score);
}
```

一行で書く

```CoffeeScript
if score > 60 then alert score
```

```JavaScript
if (score > 60) {
  alert(score);
}
```

ifを後置することができる

```CoffeeScript
 alert score　if score > 60
```

```JavaScript
if (score > 60) {
  alert(score);
}
```

真偽で条件分岐

```CoffeeScript
if score > 60
  alert "OK"
else
  alert "NG"
```

```JavaScript
if (score > 60) {
  alert("OK");
} else {
  alert("NG");
}
```

一行で書くこともできる

```CoffeeScript
if score > 60 then alert "OK" else alert "NG"
```

```JavaScript
if (score > 60) {
  alert("OK");
} else {
  alert("NG");
}
```

条件分岐した値を代入

```CoffeeScript
msg = if score > 60 then alert "OK" else alert "NG"
```

```JavaScript
var msg;

msg = score > 60 ? alert("OK") : alert("NG");
```

##7. 比較演算子・真偽値

==は===に変換される(is)
!=は!==に変換される(isnt)

比較演算子の連結

```CoffeeScript
alert "OK" if 10 < x < 20
```

```JavaScript
if ((10 < x && x < 20)) {
  alert("OK");
}
```

trueはyes,onという表現が可能
falseはno.offという表現が可能

&&はandという表現が可能
||はorという表現が可能
!はnotという表現が可能

例

```CoffeeScript
alert "OK" if answer is yes and signal isnt off
```

```JavaScript
if (answer === true && signal !== false) {
  alert("OK");
}
```

配列の中に値が存在するか

```CoffeeScript
alert "OK" if 5 in [1, 3, 5]
```

```JavaScript
if (5 === 1 || 5 === 3 || 5 === 5) {
  alert("OK");
}
```

オブジェクトの中にキーが存在するか

```CoffeeScript
obj =
  score: 52
alert "OK" if "score" of obj
```

```JavaScript
var obj;

obj = {
  score: 52
};

if ("score" in obj) {
  alert("OK");
}
```

##8. switch文を使ってみよう

```CoffeeScript
switch signal
  when "red"
    alert "STOP"
  when "blue", "green" then alert "GO!"
  when "yellow" then alert "CAUTION!"
  else alert "wrong signal!"
```

```JavaScript
switch (signal) {
  case "red":
    alert("STOP");
    break;
  case "blue":
  case "green":
    alert("GO!");
    break;
  case "yellow":
    alert("CAUTION!");
    break;
  default:
    alert("wrong signal!");
}
```

##9. 繰り返し処理

for,in

```CoffeeScript
sum = 0
for i in [0..9]
  sum += i
alert sum
```

```JavaScript
var i, j, sum;

sum = 0;

for (i = j = 0; j <= 9; i = ++j) {
  sum += i;
}

alert(sum);
```

forを後置することで一行で表現

```CoffeeScript
sum = 0
sum += i　for i in [0..9]
alert sum
```

```JavaScript
var i, j, sum;

sum = 0;

for (i = j = 0; j <= 9; i = ++j) {
  sum += i;
}

alert(sum);
```

２つ飛びで処理をする

```CoffeeScript
sum = 0
for i in [0..9]　by 2
  sum += i
alert sum
```

```JavaScript
var i, j, sum;

sum = 0;

for (i = j = 0; j <= 9; i = j += 2) {
  sum += i;
}

alert(sum);
```

配列内包(一段階ごと結果を配列として返す)

```CoffeeScript
sum = 0
total = (sum += i for i in [0..9])
alert total
```

```JavaScript
var i, sum, total;

sum = 0;

total = (function() {
  var j, results;
  results = [];
  for (i = j = 0; j <= 9; i = ++j) {
    results.push(sum += i);
  }
  return results;
})();

alert(total);
```

while文

```CoffeeScript
i = 0
sum = 0
while i < 10
  sum += i
  i++
alert sum
```

```JavaScript
var i, sum;

i = 0;

sum = 0;

while (i < 10) {
  sum += i;
  i++;
}

alert(sum);
```

while文(配列内包)

```CoffeeScript
i = 0
sum = 0
total = while i < 10
  sum += i
  i++
alert total
```

```JavaScript
var i, sum, total;

i = 0;

sum = 0;

total = (function() {
  var results;
  results = [];
  while (i < 10) {
    sum += i;
    results.push(i++);
  }
  return results;
})();

alert(total);
```

##配列・オブジェクトの繰り返し処理

配列の要素に対する繰り返し処理

```CoffeeScript
for color in ["red", "blue", "pink"]
  alert color
```

```JavaScript
var color, i, len, ref;

ref = ["red", "blue", "pink"];
for (i = 0, len = ref.length; i < len; i++) {
  color = ref[i];
  alert(color);
}
```

一行で書くこともできる

```CoffeeScript
alert color for color in ["red", "blue", "pink"]
```

```JavaScript
var color, i, len, ref;

ref = ["red", "blue", "pink"];
for (i = 0, len = ref.length; i < len; i++) {
  color = ref[i];
  alert(color);
}
```

条件をつける

```CoffeeScript
alert color for color in ["red", "blue", 
"pink"]　when color isnt "blue"
```

```JavaScript
var color, i, len, ref;

ref = ["red", "blue", "pink"];
for (i = 0, len = ref.length; i < len; i++) {
  color = ref[i];
  if (color !== "blue") {
    alert(color);
  }
}
```

何番目かを追記する

```CoffeeScript
alert "#{i}: #{color}" for color, i in ["red", "blue", 
"pink"]
```

```JavaScript
var color, i, j, len, ref;

ref = ["red", "blue", "pink"];
for (i = j = 0, len = ref.length; j < len; i = ++j) {
  color = ref[i];
  alert(i + ": " + color);
}
```

オブジェクトに対する繰り返し処理

```CoffeeScript
results =
  taguchi: 40
  fkoji: 80
  dotinstall: 60

for name, score of results
  alert "#{name}: #{score}"
```

```JavaScript
var name, results, score;

results = {
  taguchi: 40,
  fkoji: 80,
  dotinstall: 60
};

for (name in results) {
  score = results[name];
  alert(name + ": " + score);
}
```

##11. 関数

関数の書き方

function()は->記述できる
一行で書くこともできる
呼び出しは()をつける

```CoffeeScript
hello = -> alert "hello"
hello()
```

```JavaScript
var hello;

hello = function() {
  return alert("hello");
};

hello();
```

引数が必要な時

引数は->の前に記述
引数がある時の呼び出しは()不要

```CoffeeScript
hello = (name) ->
  alert "hello"
hello "taguchi"
```

```JavaScript
var hello;

hello = function(name) {
  return alert("hello");
};

hello("taguchi");
```

引数に初期値を設定

```CoffeeScript
hello = (name = "taguchi") ->
  alert "hello"
hello()
```

```JavaScript
var hello;

hello = function(name) {
  if (name == null) {
    name = "taguchi";
  }
  return alert("hello");
};

hello();
```

返り値はreturnを使わない場合最後に評価された値になる

```CoffeeScript
hello = ->　"hello"
msg = hello()
alert msg
```

```JavaScript
var hello, msg;

hello = function() {
  return "hello";
};

msg = hello();

alert(msg);
```

即時関数(関数をその場で実行する)

```CoffeeScript
do -> alert "hello"
```

```JavaScript
(function() {
  return alert("hello");
})();
```

## 12. 分割代入

複数の値を一気に代入

```CoffeeScript
[a, b, c] = [1, 5, 10]
alert a
alert b
alert c
```

```JavaScript
var a, b, c, ref;

ref = [1, 5, 10], a = ref[0], b = ref[1], c = ref[2];

alert(a);

alert(b);

alert(c);
```

値の入れ替え

```CoffeeScript
x = 10
y = 20
[x, y] = [y, x]
alert x
alert y
```

```JavaScript
var ref, x, y;

x = 10;

y = 20;

ref = [y, x], x = ref[0], y = ref[1];

alert(x);

alert(y);
```

関数の返り値を複数にする

```CoffeeScript


results = (x) -> [x, x ** 2, x ** 3]
[a, b, c] = results 5
alert a
alert b
alert c
```

```JavaScript
var a, b, c, ref, results;

results = function(x) {
  return [x, Math.pow(x, 2), Math.pow(x, 3)];
};

ref = results(5), a = ref[0], b = ref[1], c = ref[2];

alert(a);

alert(b);

alert(c);
```

オブジェクトから特定の値を取り出す

```CoffeeScript
user =
  name: "taguchi"
  score: 52
  email: "taguchi@dotinstall.com"
{name, email} = user
alert naem
alert email
```

```JavaScript
var email, name, user;

user = {
  name: "taguchi",
  score: 52,
  email: "taguchi@dotinstall.com"
};

name = user.name, email = user.email;

alert(naem);

alert(email);
```

##13. クラス

クラスの作成

クラス名は大文字から
constructorインスタンスを作るときに呼ばれるメソッド
thisは@で代換可能
constructorの引数に@プロパティを入れる事でも設定できる


```CoffeeScript
###
class User
  constructor: (name) ->
    # this.name = name
    @name = name
###

class User
  constructor: (@name) ->
  hello: -> alert "hello, #{@name}"
  
tom = new User "Tom"
alert tom.name
tom.hello()
```

```JavaScript
var User, tom;

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

  User.prototype.hello = function() {
    return alert("hello, " + this.name);
  };

  return User;

})();

tom = new User("Tom");

alert(tom.name);

tom.hello();
```

##14. クラスの継承

クラスにextendsをつけることでクラスを継承できる

```CoffeeScript
class User
  constructor: (@name) ->
  hello: -> alert "hello, #{@name}"

class AdminUser extends User

tom = new User "Tom"
# alert tom.name
# tom.hello()

bob = new AdminUser "Bob"
alert bob.name
bob.hello()
```

```JavaScript
var AdminUser, User, bob, 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;

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

  User.prototype.hello = function() {
    return alert("hello, " + this.name);
  };

  return User;

})();

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

  function AdminUser() {
    return AdminUser.__super__.constructor.apply(this, arguments);
  }

  return AdminUser;

})(User);

tom = new User("Tom");

bob = new AdminUser("Bob");

alert(bob.name);

bob.hello();
```

上書きも可能
親クラスの同名のメソッドはsuperで呼ぶことが可能

```CoffeeScript
class User
  constructor: (@name) ->
  hello: -> alert "hello, #{@name}"

class AdminUser extends User
  hello: ->
    alert "admin says..."
    super()

tom = new User "Tom"
# alert tom.name
# tom.hello()

alert bob.name
bob.hello()
```

```JavaScript
var AdminUser, User, 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;

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

  User.prototype.hello = function() {
    return alert("hello, " + this.name);
  };

  return User;

})();

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

  function AdminUser() {
    return AdminUser.__super__.constructor.apply(this, arguments);
  }

  AdminUser.prototype.hello = function() {
    alert("admin says...");
    return AdminUser.__super__.hello.call(this);
  };

  return AdminUser;

})(User);

tom = new User("Tom");

alert(bob.name);

bob.hello();
```

## 15. 存在演算子

Javascriptでは
0 '' -> falseになる

null / undefined以外でtrueを返すには?演算子を使う

```CoffeeScript
rs = if x? then "found" else "not found"
alert rs
```

```JavaScript
var rs;

rs = typeof x !== "undefined" && x !== null ? "found" : "not found";

alert(rs);
```

二項演算子

```CoffeeScript
y = 10
x = y ? 20
alert x
```

```JavaScript
var x, y;

y = 10;

x = y != null ? y : 20;

alert(x);
```

安全なアクセス演算子
オブジェクトのプロパティが存在していない場合undefinedを返す

```CoffeeScript
user =
  name: "taguchi"
alert user.score?.first
```

```JavaScript
var ref, user;

user = {
  name: "taguchi"
};

alert((ref = user.score) != null ? ref.first : void 0);
```

メソッドの場合関数かどうかの判定もする

```CoffeeScript
alert user.sayhi?()
```

```JavaScript
alert(typeof user.sayhi === "function" ? user.sayhi() : void 0);
```