回答編集履歴

4

みえるのはすべて

2016/07/14 22:25

投稿

raccy
raccy

スコア21735

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`一番内側のブロックスコープでもアクセスできます。同時に、並列にあるスコープはそれぞれ独立しています。ですので、関数`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`や`y`も`z`と同じように一番内側のブロックスコープでもアクセスできます。同時に、並列にあるスコープはそれぞれ独立しています。ですので、関数`g`内の`y`は関数`f`内の`y`への代入に影響を受けません。
72
72
 
73
73
 
74
74
 

3

`var`について注意事項を追加

2016/07/14 22:25

投稿

raccy
raccy

スコア21735

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はまだでてないよ!

2016/07/14 22:23

投稿

raccy
raccy

スコア21735

test CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
 
14
14
 
15
- クロージャを語るつもりが、環境やら静的スコープとか出てきました。まず、スコープとは何かというと変数が見える範囲(視野)の事です。下記例を見てみましょう。(以下は静的スコープであるECMAScript 2017での例になりますので、動的スコープでは全く異なることに注意してください)
15
+ クロージャを語るつもりが、環境やら静的スコープとか出てきました。まず、スコープとは何かというと変数が見える範囲(視野)の事です。下記例を見てみましょう。(以下は静的スコープであるJavaScript(ECMAScript 2016)での例になりますので、動的スコープでは全く異なることに注意してください)
16
16
 
17
17
 
18
18
 

1

クロージャではない関数などない

2016/07/14 22:19

投稿

raccy
raccy

スコア21735

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はクロージャの元祖らしいです。