JavaScriptの関数についてまとめてみる

JavaScriptの関数ってなんでしょうね…。

（この記事の実行環境はNode.jsです）

#関数を作る方法

関数を作る方法は主に3つある。

##1. function文

`function`というキーワードで関数を作る方法その1。文であることに注意。

```javascript
function hoge() {
  console.log('call hoge');
}

hoge();
fuga(); //fugaは既に作られているので、呼び出せる。

function fuga() {
  console.log('call fuga');
}
```

`function 名前(引数1, 2...) {本体}`という形式になる。
特徴は例にも書いたとおり、function文で作る関数は本文の _実行に先駆けて作られる_ ので、その行よりあとにfunction文があってもその関数を呼び出すことができる。
最初にメインロジックを書いてサブロジックをあとから付き足していく時とかは便利かも。

（仕様として説明すると結構面倒なので割愛するけれど、このfunction文での関数が作られるのはそのスコープが実行されるときの前になる。つまり、関数の中でfunction文を使って関数を作った場合、その関数が呼び出された時になる）

##2. function式

`function`というキーワードで関数を作る方法その2。文ではなく式。

```javascript
var
hoge = function () { //いわゆる無名関数とか匿名関数とか。
  console.log('call hoge');
};

hoge();
try {
  fuga(); //この時点ではfugaはundefinedなので例外を吐く。
} catch (e) { console.log(e); }

var
fuga = function fuga() { //関数に名前をつけることができる。また、ここで付けた名前はFunction#nameにしか影響しない。
  console.log('call fuga');
};

(function () {
  //スコープを作るために使うものもfunction式。
})();

//関数に渡すことも出来る。
'hoge fuga'.forEach(function (name) {
  this[name]();
}, this);
```

`function (引数1, 2...) {本体}`もしくは`function 名前(引数1, 2...) {本体}`という形式になる。
特徴は式なので、変数にそのままぶち込んだり関数に渡したりその場で呼び出したりとやりたい放題できる。JavaScriptが関数型言語といわれる所以でもある。
また、function式にもfunction文同様名前を付けられるけど、これは外側のスコープからこの名前で呼び出せるようになるわけではなく、単にその関数のnameプロパティが設定されるだけ（関数の内側からは参照できる）。じゃあ何の役に立つのかというと、スタックトレースが親切になる。コールバックにfunction式を多用する場合、スタックトレースが`<anonymous>`で埋められて絶望的な感じになるのを回避できる。

余談だけど、function文とfunction式を構文上どうやって識別しているのかというと、

  * 文の先頭に`function`がある場合はfunction文
  * そうでなければfunction式

という風にしている。で、文はそれ単体で完結しているので後に呼び出しの括弧をつけることが出来ない。
要するに、ツイートボタンなんかのスクリプトが`!function`から始まっているのは、function文と認識させて閉じたスコープの中で実行するため、ということになる。

##3.Function組み込み関数

JavaScriptの闇。`eval`以外で文字列からJavaScriptを実行できる方法の一つ。

```javascript
var
hoge = new Function('console.log("call hoge");'), //コンストラクタとして呼び出す。
fuga = Function('console.log("call fuga");'); //関数として呼び出してもいい。

hoge();
fuga();

var
fib = Function('i', 'return i <= 1 ? 1 : fib(i - 1) + fib(i - 2);'), //引数を取る場合はこうする。
pow = Function('n, m', 'return m === 0 ? 1 : m < 0 ? pow(n, m + 1) / n : pow(n, m - 1) * n;'), //引数が複数ある場合はこうする。
map = Function('f', 'xs', 'return xs.length === 0 ? [] : [f(xs[0])].concat(map(f, xs.slice(1)));'); //こうでもいい。

//関数に渡せるけど…
console.log(map(Function('x', 'return pow(fib(x), x);'), [1, 2, 3]));
```

なんて言うか、不恰好です…。シンタックスハイライトもされませんし。
しかも、実行時に文字列から関数を作りだすので、速度がネックになります。百害あって一利なしという感じです。
ならどこで使われるのかというと、文字列のJSONを読んだり（`eval`よりは安全？）後述する方法でグローバルオブジェクトを取得するのに使ったりします。

ちなみに、この`Function`で作った関数はfunction式やfunction文のようにスコープを束縛せず（ちょっと違う気がする）グローバル直下の環境で実行します。
なので、例え`'use strict';`されていても`this`が`undefined`にならずグローバルオブジェクトを取得できます。（なんか表現がおかしい）

```javascript
(function () {
  'use strict';
  console.log(typeof this); //=> 'undefined'
  console.log(typeof Function('return this;')()); //=> 'object'
})();
```

##番外編, ArrowFunction

みんな大好きArrowFunction。今のところ使えるのはFirefox 25 nightlyだけのはず。
これで作られるのは厳密にはFunctionでは無いのですけど…。

```javascript
var
hoge = () => console.log('call arrow hoge'),
fuga = () => console.log('call arrow fuga');

hoge();
fuga();
```

まともに説明すると本題から外れすぎてしまうので省略します。興味のある方は調べてみてください。
（自分は[strawman:block_lambda_revival \[ES Wiki\]](http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival)の方が好きなのですけどそれもまた別のお話）

##で、結局どれを使えばいいの？

Function組み込み関数は論外だとして、function文とfunction式。
function文の先駆けて作られるっていう性質はかなりいいと思うんだけど、知らない人からしたらややこしいだけでもあるし、やっぱり一番素直なfunction式を使えばいいと思う。なんか`'use strict 2';`でfunction文を廃止してfunction式に統一しよ―ぜ、と主張してる人も居た事だし。
あ、でも関数に名前は出来る限り付けたほうがいいです。なぜって、デバッグがかなり楽になりますから。

##最後に

あとになってからもっと書きたいことが出てきそうだから、大幅に書き換えることがあるかもしれない。

それではっ！