CoffeeScriptシンタックスの威力が発揮される記述まとめ 〜 JSおくのほそ道 #021

こんにちは、ほそ道です。

前回のCoffeeScript実行環境のまとめに引き続き、今回は文法を取り上げます。
基本的な文法はいろんな所でとっくのとうにまとめていただいているので、ほそ道的にこりゃあ便利やなーと思ったものだけ、備忘録的に垂れ流して参ります。
なお、すべての例文にJavaScriptの構文を比較対象として添えています。

[目次はこちら](http://qiita.com/setzz/items/ad9a9c99a4fda041a563)

# クラス
## クラス定義

- constructorと@引数の組み合わせで内部処理を書かなくてもいい。

```coffeescript:coffee
class Man
  constructor:(@name) ->

new Man('hosomichi')
```

```js:js
var Man;
Man = (function() {
  function Man(name) {
    this.name = name;
  }
  return Man;
})();

new Man('hosomichi');
```

## staticメンバ

- @はthisとして扱われ、thisと書くとstaticメンバ。思わず間違えないようにしたいものです。

```coffeescript:coffee
class Man
  constructor:(@name) ->
    @walk = -> console.log "dynamic walk"
  this.walk = -> console.log "static walk"

new Man("hosomichi").walk()  # dynamic walk
Man.walk()                   # static walk
```

```js:js
var Man;
Man = (function() {
  function Man(name) {
    this.name = name;
    this.walk = function() {
      return console.log("dynamic walk");
    };
  }
  Man.walk = function() {
    return console.log("static walk");
  };
  return Man;
})();

new Man("hosomichi").walk();

Man.walk();
```

## 継承

- 継承もできる。JSでキッチリやろうとすると如何に大変かがわかります。

```coffeescript:coffee
class Super
  constructor: (@name) ->
  method1: ->  'method1 super'
  method2: ->  'method2 super'

class Sub extends Super
  constructor: -> super('Okuno')
  method1: ->  'method1 sub'

h = new Sub('Hosomichi')
console.log h.name       # Okuno
console.log h.method1()  # method1 sub
console.log h.method2()  # method2 super
```

```js:js
var Sub, Super, h,
  __hasProp = {}.hasOwnProperty,
  __extends = 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; };

Super = (function() {
  function Super(name) {
    this.name = name;
  }
  Super.prototype.method1 = function() {
    return 'method1 super';
  };
  Super.prototype.method2 = function() {
    return 'method2 super';
  };
  return Super;
})();

Sub = (function(_super) {
  __extends(Sub, _super);
  function Sub() {
    Sub.__super__.constructor.call(this, 'Okuno');
  }
  Sub.prototype.method1 = function() {
    return 'method1 sub';
  };
  return Sub;
})(Super);

h = new Sub('Hosomichi');
console.log(h.name);
console.log(h.method1());
console.log(h.method2());
```

## prototypeへの追加
```coffeescript:coffee
class Man
Man::method = -> "foo"
console.log(new Man().__proto__)  # { method: [Function] }
```

```js:js
var Man;

Man = (function() {
  function Man() {}

  return Man;

})();

Man.prototype.method = function() {
  return "foo";
};

console.log(new Man().__proto__);
```

# 存在チェック
## 変数定義と値有無チェック
```coffeescript:coffee
x?
```

```js:js
typeof x !== "undefined" && x !== null;
```

## 関数が定義されていれば実行

- 関数名と括弧の間に?を入れるのが珍しいが、これで存在時のみ実行できる

```coffeescript:coffee
func = -> "foo"
console.log func?()
```

```js:js
var func;
func = function() {
  return "foo";
};
console.log(typeof func === "function" ? func() : void 0);
```

#配列

## 配列内一致検索

- `value in []`で一致する要素をselectできる
- ifの前に処理を書く事ができる(後に書く事も可能)

```coffeescript:coffee
console.log "exists" if "am" in ["I", "am", "Boy"]      # exists
console.log "exists" if "am" in ["You", "are", "Boy"]   # 出力無し
```

```js:js
if ("am" === "I" || "am" === "am" || "am" === "Boy") {
  console.log("exists");
}
if ("am" === "You" || "am" === "are" || "am" === "Boy") {
  console.log("exists");
}
```

## ループで配列生成

- 代入の右辺にforやuntil等のループを書く事で配列が生成できる。
- whenでフィルタを書ける事ができるのもモダンですね。

```coffeescript:coffee
arr = for i in [1..10] when i % 2 is 0
   "even#{i}"
console.log arr  # [ 'even2', 'even4', 'even6', 'even8', 'even10' ]
```

```js:js
var arr, i;
arr = (function() {
  var _i, _results;
  _results = [];
  for (i = _i = 1; _i <= 10; i = ++_i) {
    if (i % 2 === 0) {
      _results.push("even" + i);
    }
  }
  return _results;
})();
console.log(arr);
```

# オブジェクトリテラル
## オブジェクトのKey, Valueを出力

- `for key, val of {}`でオブジェクトのキーバリューを順に取得できる。

```coffeescript:coffee
console.log("#{k} #{v}") for k, v  of {a:'oku', b:'no', c:'hosomichi'}
```

```text:出力結果
a oku
b no
c hosomichi
```

```js:js
var k, v, _ref;

_ref = {
  a: 'oku',
  b: 'no',
  c: 'hosomichi'
};
for (k in _ref) {
  v = _ref[k];
  console.log("" + k + " " + v);
}
```

# 関数

- `...`をつける事で可変長引数が作れる。

## 可変長引数
```coffeescript:coffee
func = (arg1, arg2, arg...) -> console.log(arg...)
func(1,2,3,4,5)  # 3 4 5
```

```js:js
var func,
  __slice = [].slice;

func = function() {
  var arg, arg1, arg2;
  arg1 = arguments[0], arg2 = arguments[1], arg = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
  return console.log.apply(console, arg);
};
func(1, 2, 3, 4, 5);
```

# 総括
CoffeeScriptを使うとだいぶモダンでシャープな感じになりますね。
コンパイルされたJavaScriptもキレイで気に入ってます。
TypeScriptなどの静的型付け言語のがイイ！という人も勿論いらっしゃると思いますが
ほそ道は今の所、素早く書ける事とツールやエディタの連携が豊富な事でCoffee呑み続けて行こうかなーと思っています。

今回は以上です。