クロージャーという言葉が指すのは関数自体かそれとも仕組みか


クロージャに関して読んでいると宣言時の関数外部の変数状態も保存できる仕組みそのものを指している時もあれば、

[code]

    function outer(){
        var x = 1;
        return function (){
        x = x + 1;
        };
    }
    
[/code]

の無名関数部分をクロージャと呼んだりしてる所もあるようなのですが、どちらが正しいのでしょうか？

恐らく仕組みそのものを指す用語であって、関数の種類の一つとしてクロージャという名前が使われてるのは誤用だと思うのですが合っているでしょうか？




意見がわかれそうな内容ではありますと前置きをしておきます。

私の認識は、クロージャは仕組みそのものであって、無名関数とは分けて考えたほうがよいと思っています。

とはいえ、PHPのマニュアルのように、

<http://php.net/manual/ja/functions.anonymous.php>

> 無名関数はクロージャとも呼ばれ、 関数名を指定せずに関数を作成できるようにするものです。

というように、無名関数 = クロージャ としている例も（言語も）見かけます。

ここで、PHPの無名関数について、もっとよく見てみると  
外の変数を参照するには以下のことをしろと書いています。

> クロージャは、変数を親のスコープから引き継ぐことができます。 引き継ぐ変数は、use で渡さなければなりません。

つまりJavaScriptでは何も意識しないでも外部の変数を参照できたのに対し、PHPでは`use`によって明示的に指定する必要があるのです。

PHPでは外部の値を参照する（この外部の値を参照できるのが、私の考えるクロージャの部分です）ためにはわざわざ別の`use`という予約語を用意していることからも、無名関数とクロージャは別として考えたほうがわかりやすいというのが私の見解です。




[言語仕様](https://tc39.github.io/ecma262/)においては用語として _closure_
が定義されているわけではありませんので、世界中の人が同意する「正しい」答えはありません。ただし、この言語仕様には各所でclosureの単語が出現します。たとえば:

> [14.1.21 Runtime Semantics: Evaluation](https://tc39.github.io/ecma262/#sec-
> function-definitions-runtime-semantics-evaluation)
>
> ...  
>  _FunctionExpression: function (FormalParameters) { FunctionBody }_  
>  ...  
>  3\. Let **_closure_** be FunctionCreate(Normal, FormalParameters,
> FunctionBody, scope, strict).  
>  4\. Perform MakeConstructor( ** _closure_** ).  
>  5\. Return **_closure_**.

これは関数定義の言語仕様的な表現ですが、生成される関数オブジェクトを代入する内部的な変数の名前として **_closure_**
を用いています。この事実を採用するならば、言語仕様に書いてあるclosureとは関数functionのシノニムです。

あるいは、MDNにおいては次のような説明があります:

> [Closures - JavaScript | MDN](https://developer.mozilla.org/en-
> US/docs/Web/JavaScript/Closures)
>
> A _closure_ is **_the combination_** of a function and the lexical
> environment within which that function was declared.

この定義に従えば、クロージャとは **_関数（オブジェクト）と、その関数が定義されたスコープの組み合わせ_**
です。こちらのほうがたしかに精密に言及している気がします。

ではご指摘の件はどうかというと、私は文脈によって使い分けてもいいのではないかと思います。  
私自身は言語仕様的な用法、つまり`function===closure`で使っています(笑)。  
ただ、「関数の種類の一つとしてクロージャという名前が使われてる」のは微妙ですね。クロージャである（として定義された）関数とそうでない関数を見分ける方法がない（`isClosure(f:
Function): boolean`みたいなのが作れない）のがその根拠です。

