久しぶりにJavaScriptを思い出す(関数オブジェクト、クロージャ）

# 動機と目的

Node.js, JavaScriptを久しぶりに使おうとして、さっぱり忘れていることに気づいた。なので、ちょっと思い出すために調べたことをメモ代わりに残す。（といった使い方も Qiita は良いのだろうか？)

当面の目的は以下のTimerを使えるようになること。
[Node.js API - JavaScript のタイマー機能と非同期呼び出し | プログラマーズ雑記帳](http://yohshiy.blog.fc2.com/blog-entry-312.html)

最初にクロージャというのがわからなかった。以下の記事に解説されているが、
[JavaScriptでクロージャ入門。関数はすべてクロージャ？ - Qiita](http://qiita.com/takeharu/items/4975031faf6f7baf077a)

そもそも以下のサンプルが読めない（読み解くことができない）。

```js
var module = (function() {
  var count = 0;

  return {
    increment: function() {
      count++;
    },
    show: function() {
      console.log(count);
    }
  };

})();

module.show(); // 0

module.increment();
module.show(); // 1

console.log(count); // undefined
```

そういえば無名関数というのがあったのだな、とぼんやりと思い出す。

最初のvar moduleの定義の最後に })(); とやたらカッコが書かれているのが、なんのことか分からない。最初の}は、function() { を閉じるためのカッコ、次の)は module = ( を閉じるためのカッコである。しかし、その次の()というのが何だ？、と思った。

で、調べてみて、分かったことを以下に記述する。

# 関数の受け渡し、定義即実行、プロパティ、クロージャなど

まず、JavaScriptでは関数を、値と同じように受け渡しできる。

```js
function f1() {};
var a = f1;
```

最初のはf1という関数の定義で、何もやらない関数である。この関数をaに代入している。こういうことが可能である。これを短く書くと、以下となる。

```js
var a = function f1() {};
```

さらに、この例では関数f1は、aとして呼び出されるため、f1という名前は無駄でもある。よって、以下のように関数名すら定義から消すことができる。

```js
var a = function () {};
```

さて、では関数が代入されたaを実行するには、どうすれば良いのか、というと、以下のようにする。

```js
var a = function () {};
a();
```

aというのは = 以下の、無名の関数への「参照」であるから、実行するには()を付ける。動作確認するために、出力を加えてみる。

```js
var a = function () { console.log("TEST"); };
a();
```

ここで、関数の定義の後ろに()をつければ、定義した直後に実行できる。これが良く使われる。つまり、関数の定義と実行を一括で記述する簡便な方法だ。

```js
var a = function () { console.log("TEST"); } ();
```

こうすると、実行された結果がaに代入される。この関数は何もreturnしないので、aには何も代入されない。

```js
var a = function () { console.log("TEST"); } ();
console.log(a);
```

上記のコードを実行すると、TESTの後に、「undefined」が出力される。aには何も入っていない、という意味である。

以下のように関数の中で returnを定義すれば。aには実行結果として、1が代入されることになる。

```js
var a = function () {
  return 1;
} ();

console.log(a);
```

最初に述べたように、JavaScriptでは関数を値と同じように受け渡しできるため、この戻り値も関数にすることができる。

```js
var a = function () {
  return function () {
    console.log("TEST");
  }
} ();
```

こうすると、aには、関数を実行した結果、return の後ろの関数がaに代入されることになる。よって、以下のように戻ってきた関数を実行することができる。

```js
var a = function () {
  return function () {
    console.log("TEST");
  }
} ();

a();
```

最初のコードを理解するには、さらにプロパティを知る必要がある。return文の中に、プロパティが定義されている。return文に２つのプロパティを入れると、例えば以下のようになる。

```js
var a = function () {
    return {
        propA: function () { console.log("A"); },
        propB: function () { console.log("B"); }
    };
} ();

a.propA();
a.propB();
```

aはpropAと、propBという２つのプロパティを持つ関数である。それぞれのプロパティには、別の関数が割り当てられている。

ここまで理解できると、クロージャを解説している最初のプログラムがわかるようになる。

```js
var module = (function() {
  var count = 0;

  return {
    increment: function() {
      count++;
    },
    show: function() {
      console.log(count);
    }
  };

})();

module.show(); // 0
module.increment();
module.show(); // 1

// console.log(count); // undefined
```

ちなみに、module = (の(は不要である。　ここで不思議がらねばならないのは、countという変数の値が、保持されている点である。関数の中で定義された関数は、その属しているスコープの変数も一緒に保持するようになっている。

moduleという関数は、countの値も含めて更新されている。これがクロージャである。値も含めて保持していることを使うと、次のようなプログラムを書くこともできる。

```js
function counter() {
    var count = 0;

    return {
        increment: function() { count++;
    },
        show: function() {
            console.log(count);
        }
    };
};

var mod1 = counter();
var mod2 = counter();

mod1.show(); // 0                                                                                      
mod1.increment();
mod1.show(); // 1                                                                                      

mod2.show(); // 0                                                                                      
mod2.increment();
mod2.show(); // 1          
```

counterの実行結果、つまりreturnの後ろの関数群を mod1 と mod2 という２つの変数に代入する。
それぞれ代入時点で、var count = 0でcountが初期化される。

その後、incrementが呼ばれるたびに内部に保持しているcountが+1される。
（mod1がオブジェクト、その属性値がcountという感じになる。）

外から直接操作できない count は、まるでプライベート変数のようである。
（ちなみに、JavaScriptにはプライベート変数は無いらしい）

なるほど。


# まとめ

- JavasScriptでは、関数も代入したり、引数や、返り値に使うことができる。
- 関数を定義した直後に実行することもできる。
- 実行オプション付きの関数を、変数に代入すると、実行結果のreturnの中身が代入される。
- 関数をreturnすると、関数が代入される。
- return内にプロパティを定義すれば、プロパティ付きのreturnを返すことができる。
- 関数内部で定義した関数を、代入した変数（オブジェクト）では、中の変数の値も保持し続ける。
- この変数値も保持し続ける関数をクロージャと呼ぶ。
- クロージャを使うとプライベート変数のようなものが実現できる。
- JavaScriptは、スクリプト言語としての便利さを追求したものだと分かった。

- あと、Qiitaは、プログラムを記述するのに、とても便利だと分かった。