teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

コメントを受けて追記

2020/01/15 11:22

投稿

AkitoshiManabe
AkitoshiManabe

スコア5434

answer CHANGED
@@ -29,4 +29,38 @@
29
29
  クロージャは ``let`` 宣言が登場する以前(簡単に内容を書き換えられてしまう ``var`` しか使えなかった時代)に、如何にして書き換えられないようにするか?といったトリックです。
30
30
  上記の通り、**スコープを変える**ことで達成しています。
31
31
 
32
- ``let`` が使えるモダンな環境では、使うことも無くなったように思いますが、古いコードを読むためにも知っておくべき内容となります。理解のポイントは**スコープの違い**となります。
32
+ ``let`` が使えるモダンな環境では、使うことも無くなったように思いますが、古いコードを読むためにも知っておくべき内容となります。理解のポイントは**スコープの違い**となります。
33
+
34
+ ----
35
+ コメントを受けて追記)
36
+ [Wikipedia クロージャ](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3)
37
+
38
+ 即時関数は「**関数宣言**+**実行構文**(引数を受け付ける括弧)」で、無名である必要はありません。
39
+
40
+ ```
41
+ // ご質問のコードを named関数 にした例
42
+ let increment=(function enclosure(){
43
+ let count=0;
44
+ return function closure(){
45
+ count+=1;
46
+ console.log(count);
47
+ }
48
+ })();
49
+ ```
50
+
51
+ 即時関数の実行は enclosureの実行ですので、その返却値(内部で関数宣言されたclosure)が、increment に代入されます(この代入で closure への参照となる)。
52
+
53
+ > (この時点で即時関数の役割が消える、let count=0が参照されなくなる)
54
+
55
+ 即時関数の役割は、enclosure内で宣言された変数とclosure関数の保持になります(メモリ上には残る)。
56
+ また、count は、直接参照されなくなりますが、closureを介して間接的に利用はできます。
57
+
58
+ > 内側の関数をクロージャにするために return文を使っているのですか?
59
+
60
+ increment に closure を参照させ、increment() を実行できるようにするための return です。
61
+ WikiPediaの説明のように、Javascript では 「関数の中で宣言される関数」はクロージャになりうるものです。
62
+
63
+ ちなみに、return を外すと、「Uncaught TypeError: increment is not a function」になりませんか?
64
+
65
+ さいごに
66
+ shiracamus さんの回答にもあるように、「コードを追いかけること」も大事になります。

2

コードの加筆

2020/01/15 11:22

投稿

AkitoshiManabe
AkitoshiManabe

スコア5434

answer CHANGED
@@ -7,6 +7,7 @@
7
7
  var increment=function(){
8
8
  count+=1;
9
9
  console.log(count);
10
+ return count;
10
11
  }
11
12
  ```
12
13
  > ①即時関数にするのはなぜか

1

追記

2020/01/15 09:50

投稿

AkitoshiManabe
AkitoshiManabe

スコア5434

answer CHANGED
@@ -2,9 +2,9 @@
2
2
  (「①の回答」に繋がります)
3
3
 
4
4
  ```
5
- let count=0;
5
+ var count=0;
6
6
 
7
- let increment=function(){
7
+ var increment=function(){
8
8
  count+=1;
9
9
  console.log(count);
10
10
  }
@@ -21,4 +21,11 @@
21
21
  > ③let count=0で初期化されない(countの値が保持される)のはなぜか
22
22
 
23
23
  即時関数が実行されるとき(increment宣言時)にcount は初期化され、
24
- 即時関数のスコープ内で値を保持します。
24
+ 即時関数のスコープ内で値を保持します。
25
+
26
+ ----
27
+ 追記)
28
+ クロージャは ``let`` 宣言が登場する以前(簡単に内容を書き換えられてしまう ``var`` しか使えなかった時代)に、如何にして書き換えられないようにするか?といったトリックです。
29
+ 上記の通り、**スコープを変える**ことで達成しています。
30
+
31
+ ``let`` が使えるモダンな環境では、使うことも無くなったように思いますが、古いコードを読むためにも知っておくべき内容となります。理解のポイントは**スコープの違い**となります。