若干functionalなJavaScript, CoffeeScriptの個人的に使う小技集

だいたいJavaScript、CoffeeScript両方のコードサンプルを書いてあるけど、横着してそうでないのもチラホラ。

## letに相当する何か / スコープを守ろう

まずは簡単なところから。

### JavaScriptは関数スコープ

`for`や`if`等でスコープが作られる文化圏から来た人は注意。
思わぬところで思わぬ変数にアクセスできる。

```js
var sum = 0;
for (var i = 0; i < 10; i++) {
  sum += i;
}
console.log(i); // -> 10
```

```js
// 変数を局所化
var sum = (function () {
  var s = 0;
  for (var i = 0; i < 10; i++) {
    s += i;
  }
  return s;
}());
console.log(i); // -> undefined
```

## カプセル化

`prototype` + `new` でOOPっぽく書きたいニーズもあるようだが、それだと全てのプロパティがpublicになるので (クラスのないJavaScriptで public という言い方をしていいのか悩むところだが) privateを実現するにはclosureを使う。

```js
var obj = (function () {
  var invisibleVar = 1;
  return {
    get: function () {return invisibleVar;},
    add: function (num) {invisibleVar += num;}
  };
}());
```

### カプセル化 / CoffeeScript

とくに関数リテラルのすっきり感は異常。

```coffeescript
obj = do ->
  invisibleVar = 1;
  {
    get: -> invisibleVar
    add: (num) -> invisibleVar += num
  }
```

CoffeeScriptにはクラスがあるが、privateなプロパティは作れない。


### ファクトリにしてもいい

```coffeescript
factory = ->
  invisibleVar = 1;
  {
    get: -> invisibleVar
    add: (num) -> invisibleVar += num
  }
o1 = factory()
o2 = factory()
```

JavaScriptのサンプルは割愛。

## new (prototype) vs closure

ぶっちゃけnew (prototype) の方が高速でメモリ使用量も少ない。

http://macwright.org/2013/01/22/javascript-module-pattern-memory-and-closures.html

* new (prototype) のメリット
  * 速度とメモリ消費量の点で優れる
  * `Object.prototype.isPrototypeOf`を使って型の判定みたいなことができる
* closureのメリット
  * カプセル化ができる
  * new/thisのトリッキーな挙動から逃れられる

## CoffeeScriptの`switch`で使える`progn`っぽい何か

※このセクションは不要だと分かりました

`then`の後に複数の式を書きたい、という場合。

`then`を書かなければいいだけ、とコメントでご指摘頂いて判明したのですが、当初は以下のように記述していました。
一応誤情報として残しておきます。

### 誤

```coffeescript
score = 76
grade = switch
  when score < 60 then 'F'
  when score < 70 then 'D'
  when score < 80 then 'C'
  when score < 90 then do ->
    r = Math.random()
    score + r
  else 'A'
```

無名関数でラップしないと構文エラー。

### 正

ところがこれで済むようです。

```coffeescript
score = 76
grade = switch
  when score < 60 then 'F'
  when score < 70 then 'D'
  when score < 80 then 'C'
  when score < 90
    r = Math.random()
    score + r
  else 'A'
```

## 部分適用

蛇足だけどカリー化とは厳密には異なる。

```js
// JavaScript
var fun1 = function (a, b) {
  return a + b;
};

var fun2 = fun1.bind(null, 1);
console.log(fun2(2)); // -> 3
```

```coffeescript
# CoffeeScript
fun1 = (a, b) ->
   a + b;

fun2 = fun1.bind null, 1
console.log(fun2 2) # -> 3
```

## オブジェクトAのメソッドを, オブジェクトBが俺のモノだと実行する

call, applyの違いはメソッドへの引数の渡し方

```js
// JavaScript
a.prototype.method.call(b, arg1, arg2);
a.prototype.method.apply(b, [arg1, arg2]);
```

```coffeescript
# CoffeeScript
a::method.call b, arg1, arg2
a::method.apply b, [arg1, arg2]
```

## 配列のようで配列でない何かを配列にする

`[]`で要素にアクセスできて`length`プロパティを持つものならいけるっぽい

`Function.prototype.apply`の応用例としてもどうぞ。

```js
// JavaScript
function f () {
  var argArr = Array.prototype.slice.call(arguments);
}
var strArr = Array.prototype.slice.call('hogehoge');
```

```coffeescript
# CoffeeScript
f = ->
  argArr = Array::slice.call arguments
strArr = Array::slice.call 'hogehoge'
```

文字列の配列化なら正直こっちの方が簡潔

```coffeescript
strArr = 'hogehoge'.split ''
```

## 配列操作のコールバックで忘れがちな引数

`forEach`、`map`、`some`等の第二引数、第三引数は、indexと元の配列である。
`reduce`ならば第三、第四引数がこれに該当。

```js
// JavaScript
[1, 1, 2, 3, 5].reduce(function (a, b, index, array) {
  return a + b;
}, 'initial value'); // reduce系なら初期値をここでセット
```

```coffeescript
# CoffeeScript
[1, 1, 2, 3, 5].reduce(((a, b, index, array) ->
  a + b
), 'initial value')

# CoffeeScriptならリスト内包表記も使えるから合わせ技が便利よね
```


### 元の配列の渡し方はどちらがよい？

その1、レキシカルスコープで渡す

```js
array1.map(function (e, i) {
  return array1[i + 1] + e;
});
```

その2、コールバックの引数を使う

```js
array1.map(function (e, i, arr) {
  return arr[i + 1] + e;
});
```

### ベンチマークによる速度比較

コールバックの引数を使った方が速い。恐らく変数名の解決のコストがないため。

以下のコードをChromium 30.0で実行したところ、36.4msec vs 218.8msecでコールバックの引数を使った方が高速だった。

```js
function elapse (f) {
   var i,
       times = 10,
       start = (new Date()).getTime();
    for (i = 0; i < times; i++) {
        f();
    }
   console.log(((new Date()).getTime() - start) / times + 'msec');
}

var a = [], i, start;
for (var i = 0; i < 1000*1000; i++) {
    a.push(i);
}

elapse(function () {
    a.forEach(function(e, i, arr) {
        var l = arr.length;
    });
});

elapse(function () {
    a.forEach(function(e, i, arr) {
        var l = a.length;
    });
});
```

### 解説

JavaScriptでは、使用された変数の名前が現在実行している関数のスコープにない場合、
その1つ外側の関数のスコープに同名の変数がないか探しにいき、そこでもなければさらに外側を探し…
と変数の解決を行おうとする (グローバルスコープにもなければ`undefined`となる) 。

したがって、より近いスコープに変数があるほど効率はよくなる。

なお上記のベンチマークの例だと、配列の変数が1つどころが2つ外側のスコープにあるので、
あまり厳密な測定ではないが、そこは気にしないということで。

## 関数を否定した関数を返す関数

あんまり使わないかな？

DOMイベントで、何かがOnの時とOffの時にそれぞれコールバックを設定する時に、
Offの時はOnの時の否定を取るような場合に、こういうのを書くとDRYになるかと (日本語が訳わからん) 。

```js
// JavaScript
var fun = function (a, b) {
    return a < b;
};

var negate = function (f) {
  return function () {
    var args = Array.prototype.slice.call(arguments);
    return !f.apply(this, args);
  };
};

var nFun = negate(fun);

console.log(fun(1, 2)); // -> true
console.log(nFun(1, 2)); // -> false
```

```coffeescript
# CoffeeScript
fun = (a, b) -> a < b

negate = (f) ->
  ->
    args = Array::slice.call(arguments);
    !f.apply(this, args);

nFun = negate fun
```

## mix-in

これはまだ試験運用中。

```js
var mixin = function (obj, module) {
  var key, property;
  for (key in module) {
    property = module[key];
    if (module.hasOwnProperty(key) && typeof property === 'function') {
      obj[key] = function () {
        return module[key].apply(obj, Array.prototype.slice(arguments));
      };
    }
  }
  return obj;
};

mixin(myObject, myModule);
```

### CoffeeScriptだとclass等というものが使えるらしい

delegateと見せかけた何か

```coffeescript
myModule =
  f: -> 'OK'

mixin = (clazz, module) ->
  moduleName = "__module__#{(new Date()).getTime()}"
  clazz.prototype[moduleName] = module
  for name, property of module when typeof property is 'function'
    # IIFE (後述)
    do (_name = name, fn = property) ->
      clazz.prototype[_name] = ->
        fn.apply(this[moduleName], Array::slice.call(arguments))

class Hoge
  constructor: ->

mixin Hoge, myModule
```

## IIFE (即時関数) とはなんぞや

匿名関数を作ってそのまま実行しているものを指す。冒頭でスコープを作るのに使ったアレ。ここではループの変数を固定化するのに用いている。

```coffeescript
# 悪い例
myModule =
  foo: -> 'FOO'
  bar: -> 'BAR'

mixin = (clazz, module) ->
  moduleName = "__module__#{(new Date()).getTime()}"
  clazz.prototype[moduleName] = module
  for name, property of module when typeof property is 'function'
    clazz.prototype[name] = ->
      property.apply(this[moduleName], Array::slice.call(arguments))

mixin(Hoge, myModule)

console.log Hoge::foo()
```

関数`foo`をコールすると`BAR`って返ってきやがります。
これは、JavaScriptの変数が関数スコープなのとClosureの合わせ技なためで、forループで使っている`property`という変数が、ループの最後にセットされた値を参照することになるため。

なので関数の引数として変数をbindingすることによってこの問題を回避する。

```coffeescript
for name, property of module when typeof property is 'function'
  do (_name = name, fn = property) ->
    clazz.prototype[_name] = ->
      fn.apply(this[moduleName], Array::slice.call(arguments))
```

### CoffeeScriptをらしく美しく / `do`と`when`

最初、即時関数を素朴にJavaScriptそのまんまで

```coffeescript
for name, property of module
  if typeof property is 'function'
    ((_name, fn) ->
      clazz.prototype[_name] = ->
        fn.apply(this[moduleName], Array::slice.call(arguments))
    )(name, property)
```

とやっていたところ、※欄にて`do`、`when`を使ってより簡潔に記述可能と教えて頂き、現在の形に修正しています。

## immutableにしたいかね？

```js
var immutable = Object.freeze({
  foo: 'FOO',
  bar: 'BAR'
});

immutable.foo = 'A'; // 返事がないただの屍

(function  () {
  // use strictによって例外が発生するようになる
  'use strict';
  immutable.foo = 'B'; // TypeError
})();
```