関数のお尻についてるｆ() ←この丸カッコについて考えてみた

普段、関数を書く時、<b>`f()`</b> ←こういう丸カッコを何気なく使うと思いますが、

丸カッコの意味について、再考させられる機会があったので書き留めておきます。


#0　結論

いきなり結論ですが、例えば次のような関数`f`があった場合、

```javascript
function f(){
  return "hello!";  
}
```

> <b>f</b> →　関数の実体（entity)
> <b>f()</b> →　関数の返り値（return value）

であるということです。実際、

```javascript
console.log(f); //--> [Function: f]
console.log(f()); //-->  hello!
```

となります・・・？何を当たり前のことを、と思われるかもしれませんが、
この事実をもう少しだけ、掘り下げてみます。


#1　検証その１

わかりやすい事例として、よく見かけるクロージャの例を挙げます。

```javascript
function greet() {
    var x = '';
    return (function(){
        x += 'hello!';
        return x;
    });
}
```
```javascript
var g = greet(); 
console.log(g()); //--> hello!
console.log(g()); //--> hello!hello!
console.log(g()); //--> hello!hello!hello!
```

これは、関数`greet`の返り値である無名関数 `function(){...}` がグローバル変数`g`から参照されることによって、`function(){...}` 内の変数`x`もグローバル変数`g`から参照され、変数`x`の値がグローバル空間に保持されるという現象です。

*※グローバルオブジェクトから参照をたどって行き着くことのできる値は、 ガベージコレクション（メモリの掃除のような機能）の対象から外れるので、グローバル空間に値が保持される、ということだったかと思います。*

変数の値を保持するために有効な方法ですが、メモリリークの温床ともなるので無用な多用は控えましょう・・・とよく諭されます。

では、上記の処理を次のように書きかえるとどうなるでしょうか？

#2　検証その２

```javascript
function greet() {
    var x = '';
    return (function(){
        x += 'hello!';
        return x;
    });
}
```

```javascript
var g = greet;
console.log(g()()); 
console.log(g()()); 
console.log(g()()); //--> ?
```

前の例との違いは、グローバル変数`g`に代入されているのが返り値`greet()`でなく関数の実体`greet`というところです。ちなみに、`g()()`と()が２つ繋がっているのは、`greet`の返り値である無名関数 `function(){...}`の返り値を取り出すためです。

これもクロージャと似ていますが、前の例とはグローバル空間に保持される範囲が異なります。

ここでは関数の実体`greet`をそのまま保持しているため、返り値である無名関数 `function(){...}`だけでなく`var x=""` の処理部分も一緒に保持されます。したがって、出力は次のようになります。

```javascript
var g = greet;
console.log(g()()); //--> hello!
console.log(g()()); //--> hello!
console.log(g()()); //--> hello!
```
Javascriptでは関数型の変数への代入は参照渡しとなるため、メモリへの影響はほとんどないと思われますが、関数を毎回実行するため処理量は増えます。

もう１つ例を挙げます。次の場合はどうなるでしょうか？

#3　検証その３
```javascript
function greet(){
   var x="";
   return (function(){
      x += "hello!";
      return ()=>x;   //g()で結果を取得したいので、返り値はxを返り値とする関数にする
   })();              //<--末尾に()をつけるのがポイント
}
```
```javascript
var g = greet(); 
console.log(g()); 
console.log(g()); 
console.log(g()); //--> ?
```
検証その１と同様、グローバル変数`g`への代入部分は、関数`greet`の返り値`greet()`を用いています。

一方、関数`greet`の定義部分を見ると、返り値には、無名関数の代わりに、無名関数の末尾に()をつけて即時関数としたものが指定されています。

つまり、検証その１との違いは、グローバル変数`g`に代入されるのが無名関数そのものでなく、無名関数の実行結果であるということです。

したがって、出力は次のようになります。

```javascript
var g = greet(); 
console.log(g()); //--> hello!
console.log(g()); //--> hello!
console.log(g()); //--> hello!
```

ここで、グローバル変数`g`から参照可能なのは無名関数 `function(){...}`実行結果のみで、無名関数 `function(){...}`内の変数`x`へアクセスすることはできません。つまり、これはクロージャではありません。

`g`に保持されるのは`()=>'hello!'`の部分のみなので、上記３つの例の中では、メモリ消費量が比較的少なく、かつ処理量も少なくなります。


#4　もっと実用的な例

実際にJavascriptを使って何か作る場合は、以下のように疑似クラス等を定義して使用することが多いかと思います。

```js
function Greet(){
    var x = 'hello!';
    
    Greet.prototype.goodbye = function(){
        x += 'goodbye!';
        return x;
    };
    Greet.prototype.hello =  function(){
        return x;
    };
}
```
本来は`Greet.prototype`を関数`Greet`の外に出す方が処理的にはベターなのですが、変数`x`をプライベートメンバとして扱いたいので、便宜的に中に入れています。

検証１のクロージャと全く同じで、インスタンス`g`にメンバ変数`x`の値が保持されるため、次のような出力になります。

```js
var g = new Greet();
console.log(g.goodbye());  //--> hello!goodbye!
console.log(g.hello());    //--> hello!goodbye! 
```

ここで、`Greet.prototype.hello`をメンバ変数`x`の初期値を返すだけの関数にしたい場合は、どうしたらいいでしょうか？

```js
var g = new Greet();
console.log(g.goodbye());  //--> hello!goodbye!
console.log(g.hello());    //--> hello!　 <--こうしたい
```
検証１～３の結果を用いて、メンバ変数`x`の値が変わらないようにする方法を考えてみます。


#5　もっと実用的な例（メンバ変数の値が変わらないようにする）

```js
function Greet(){
    var x = 'hello!';
    
    Greet.prototype.goodbye = (function(){
        x += 'goodbye!';
        return ()=>x;
    })();
    Greet.prototype.hello =  function(){
        return x;
    };
}
```
検証その３と同様、`Greet.prototype.goodbye `に即時関数を割り当てているので、`x`の値が保持されないように見えますが、これを実行すると

```js
var g = new Greet();
console.log(g.goodbye());  //--> hello!goodbye!
console.log(g.hello());    //--> hello!goodbye! 
```

・・・？　期待通りになりません。

おそらくですが、検証その３では、関数`greet`は無名関数の返り値を返していたのに対し、上の例では関数`Greet`が、new演算子の仕様により、暗黙的に関数`Greet`の実体を返しているためだと思われます。関数`Greet`のスコープ全体がグローバル変数`g`に割り当てられることにより、変数`x`が保持されているのだと思われます。

これを回避するためには、例えば次のような案が考えられます。


```js
function Greet(){
    var x = 'hello!';
    
    Greet.prototype.goodbye = (function(y){
        y += 'goodbye!';
        return ()=>y;
    })(x);
    Greet.prototype.hello =  function(){
        return x;
    };
}
```

こうすると、相変わらず変数`x`の値は保持されているものの、`Greet.prototype.goodbye `中では仮引数`y`のみが使用されているため、変数`x`が侵襲されることがありません。

```js
var g = new Greet();
console.log(g.goodbye());  //--> hello!goodbye!
console.log(g.hello());    //--> hello!
```


#6　つまり・・・どういうことだってばよ？

結局のところ、何が言いたいのかよくわからないエントリになってしまいましたが、

要するに、<b>`f()`</b>←この丸カッコの正体は、

<b> () の直前の関数を実行し、処理結果を得る演算子 </b>

と言い換えることができ、

<b>f() は処理結果であり、関数そのものではない！ </b>


という簡単だけど重要な事実をしっかりと意識することで、

変数の値の管理やメモリに配慮した設計に役立つかもしれない 
・・・ということです。

---
本エントリは、独自の実験に基づいており、誤認識等あるかも知れませんので、
コメント等でご指摘いただけると幸いです。