回答編集履歴
4
みえるのはすべて
test
CHANGED
@@ -68,7 +68,7 @@
|
|
68
68
|
|
69
69
|
|
70
70
|
|
71
|
-
JavaScriptでは主に大域スコープ(global scope)、関数スコープ(function scope)、ブロックスコープ(block scope)の三つがあります(他にevalスコープ(eval scope)とモジュールスコープ(module scope)がありますが、ここでは省略します。なお、名称はECMAScript 2016仕様書での○○DeclarationInstantiationとなっているものから取ってきています)。変数は宣言された場所のスコープに関連づけられ、そのスコープの範囲内で有効になります(`var`で宣言された場合のみ特殊で、ブロックスコープ上であっても一番間近の外側にある大域スコープまたは関数スコープに関連づけられます)。上では、`x`は大域スコープ、`y`は関数スコープ、`z`はブロックスコープが有効範囲です。しかし、スコープは外から内へ浸食しており、内側のスコープは外側のスコープを見ることができます。ですので、`x`
|
71
|
+
JavaScriptでは主に大域スコープ(global scope)、関数スコープ(function scope)、ブロックスコープ(block scope)の三つがあります(他にevalスコープ(eval scope)とモジュールスコープ(module scope)がありますが、ここでは省略します。なお、名称はECMAScript 2016仕様書での○○DeclarationInstantiationとなっているものから取ってきています)。変数は宣言された場所のスコープに関連づけられ、そのスコープの範囲内で有効になります(`var`で宣言された場合のみ特殊で、ブロックスコープ上であっても一番間近の外側にある大域スコープまたは関数スコープに関連づけられます)。上では、`x`は大域スコープ、`y`は関数スコープ、`z`はブロックスコープが有効範囲です。しかし、スコープは外から内へ浸食しており、内側のスコープは外側のスコープを見ることができます。ですので、`x`や`y`も`z`と同じように一番内側のブロックスコープでもアクセスできます。同時に、並列にあるスコープはそれぞれ独立しています。ですので、関数`g`内の`y`は関数`f`内の`y`への代入に影響を受けません。
|
72
72
|
|
73
73
|
|
74
74
|
|
3
`var`について注意事項を追加
test
CHANGED
@@ -68,7 +68,7 @@
|
|
68
68
|
|
69
69
|
|
70
70
|
|
71
|
-
JavaScriptでは主に大域スコープ(global scope)、関数スコープ(function scope)、ブロックスコープ(block scope)の三つがあります(他にevalスコープ(eval scope)とモジュールスコープ(module scope)がありますが、ここでは省略します。なお、名称はECMAScript 2016仕様書での○○DeclarationInstantiationとなっているものから取ってきています)。変数は宣言された場所のスコープに関連づけられ、そのスコープの範囲内で有効になります。上では、`x`は大域スコープ、`y`は関数スコープ、`z`はブロックスコープが有効範囲です。しかし、スコープは外から内へ浸食しており、内側のスコープは外側のスコープを見ることができます。ですので、`x`は一番内側のブロックスコープでもアクセスできます。同時に、並列にあるスコープはそれぞれ独立しています。ですので、関数`g`内の`y`は関数`f`内の`y`への代入に影響を受けません。
|
71
|
+
JavaScriptでは主に大域スコープ(global scope)、関数スコープ(function scope)、ブロックスコープ(block scope)の三つがあります(他にevalスコープ(eval scope)とモジュールスコープ(module scope)がありますが、ここでは省略します。なお、名称はECMAScript 2016仕様書での○○DeclarationInstantiationとなっているものから取ってきています)。変数は宣言された場所のスコープに関連づけられ、そのスコープの範囲内で有効になります(`var`で宣言された場合のみ特殊で、ブロックスコープ上であっても一番間近の外側にある大域スコープまたは関数スコープに関連づけられます)。上では、`x`は大域スコープ、`y`は関数スコープ、`z`はブロックスコープが有効範囲です。しかし、スコープは外から内へ浸食しており、内側のスコープは外側のスコープを見ることができます。ですので、`x`は一番内側のブロックスコープでもアクセスできます。同時に、並列にあるスコープはそれぞれ独立しています。ですので、関数`g`内の`y`は関数`f`内の`y`への代入に影響を受けません。
|
72
72
|
|
73
73
|
|
74
74
|
|
2
ECMAScript 2017はまだでてないよ!
test
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
|
14
14
|
|
15
|
-
クロージャを語るつもりが、環境やら静的スコープとか出てきました。まず、スコープとは何かというと変数が見える範囲(視野)の事です。下記例を見てみましょう。(以下は静的スコープであるECMAScript 201
|
15
|
+
クロージャを語るつもりが、環境やら静的スコープとか出てきました。まず、スコープとは何かというと変数が見える範囲(視野)の事です。下記例を見てみましょう。(以下は静的スコープであるJavaScript(ECMAScript 2016)での例になりますので、動的スコープでは全く異なることに注意してください)
|
16
16
|
|
17
17
|
|
18
18
|
|
1
クロージャではない関数などない
test
CHANGED
@@ -114,7 +114,7 @@
|
|
114
114
|
|
115
115
|
|
116
116
|
|
117
|
-
このように、各スコープでわかれたそれぞれの場所を**環境**と言います。それぞれの環境にはそのスコープで宣言された変数が**束縛**されており、また、外側にどんな環境があるかも知っています。
|
117
|
+
このように、各スコープでわかれたそれぞれの場所を**環境**と言います。それぞれの環境にはそのスコープで宣言された変数が**束縛**されており、また、外側にどんな環境があるかも知っています(外側の環境をどんどん繋いでいく仕組みをスコープチェーンといいます)。
|
118
118
|
|
119
119
|
|
120
120
|
|
@@ -186,9 +186,19 @@
|
|
186
186
|
|
187
187
|
|
188
188
|
|
189
|
+
###JavaScriptでクロージャである関数とクロージャではない関数
|
190
|
+
|
191
|
+
結論から言いますと、JavaScriptでの全ての関数(名前有り無しなどに関わらず)はクロージャを**必ず含んでいます**。理由は二つあります。一つは、JavaScriptは関数定義時にその中身を一切評価しないため、中で外側の環境にある変数を使っているかわからないと言うこと。もう一つは、その関数が現在のスコープが終了した後にも使われる事になるかを定義時に判断できないと言うこと。この二つの理由により、JavaScriptエンジンはその関数がクロージャとして動く必要があるのか、それともクロージャでなくても良いのかを関数が作成される定義時に判断することができないからです。
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
※ 他の言語も同じとは限りません。他の方が示したようにPHPでは普通の関数をクロージャにするかしないかをuseキーワードで選択できます(ただし無名関数は必ずクロージャになる、というよりClosureのインスタンスを作るのが無名関数であるらしい)。
|
196
|
+
|
197
|
+
|
198
|
+
|
189
199
|
###JavaScript以外のクロージャ
|
190
200
|
|
191
|
-
クロージャも実は色々種類が
|
201
|
+
クロージャも実は色々種類があり、実装も様々です。上のことは他の言語でもだいたい同じように言えますが、細部が異なります。
|
192
202
|
|
193
203
|
|
194
204
|
|
@@ -287,3 +297,7 @@
|
|
287
297
|
|
288
298
|
|
289
299
|
* Haskellは遅延評価という仕組みであるため、束縛している変数が実際に評価されるときにはスコープが終了した後になる場合があります。そのため、そのときの各変数のコピーでは無く、環境自体を含んでいる必要があります。つまり、**Haskellは本当のクロージャを実装しています**。ただし、immutableという性質上、JavaScriptのカウンタの例のようなことはできません。
|
300
|
+
|
301
|
+
* Pythonはちょっと特殊っぽいです。調査中。
|
302
|
+
|
303
|
+
* Schemeはクロージャの元祖らしいです。
|