レプリカ


主にjavascriptとpythonを用いるため,関数に関数が含まれているとは思えない.ただし、javaがプライマリメソッド内でメソッドを定義および使用しようとすると、エラーが発生します.
javascriptでは、内部関数が外部関数にアクセスできる脈絡をcloserと呼びます.

エンクロージャ

function outter() {
  let text = 'text in outter';
  function inner() {
  	console.log('use ' + text);  
  }
  inner();
}
上記のコードでinnerと定義されている関数では、textという変数が使用されます.inner関数内のtextは定義されていないので、外部関数outterで定義されたtextが検索されて出力される.このように,内部関数が外部関数にアクセスする脈絡を閉パケットと呼ぶ.

妖怪

function outter() {
  let text = 'text in outter';
  function inner() {
  	console.log('use ' + text);  
  }
  return inner;
}

let call = outter();
call(); // use text in outter
上記のコードから見ると、inner関数はoutterの内部に定義された関数である.outter関数は、定義されたinner関数を返します.
グローバルscopeでは、callという変数にoutter関数の実行結果(内部定義のinner関数を渡す)を渡し、callを実行するとuse text in outterという値を呼び出す.
まあいいけど、よく考えたら、innerは、textという名前の変数を使用します.
これにより、outter関数で定義された値が得られます.
しかし、outter関数は、callを呼び出す前に使用され、終了した可能性がありますが、どのようにして値を取得しますか?
モジュールは、内部関数が外部関数の脈絡にアクセスできるだけでなく、内部関数で外部関数の変数を使用すると、内部関数が終了するまで変数は変わらないことを示します.

もっと妖しい


closureの概念を学習する場合、settimeoutに関連付けて説明することがあります.
function countSec() {
  for (var i = 1; i <= 10; i++) {
    setTimeout(() => {
      console.log(i);
    }, i * 1000)
  }
};

countSec();
console.log('외부함수 종료');
上のコードでは、1から10まで1秒ごとに出力するために書かれたコードが見られます.しかし、結果として11は1秒ごとに出力される.setTimeout(f, time)は、実行時間(ms)後のfを許可するコードである.(非同期運転)setTimeout iの値を取ってそのまま使用します.このため、1秒ごとに出力することができる.(このとき、iは11の値で文を繰り返します.)
しかし、setTimeoutの匿名関数は、外部関数の終了後に呼び出される.したがって、사라지지 않은 iの値が得られ、実行されるモジュールが形成される.しかし、既にiの値が11であるため、出力11となる.
わかりにくい
  • settimeoutの最初のパラメータ匿名関数でiを使用します.次に、2番目のパラメータでiを使用して間隔を置きます.
  • の2番目のパラメータでは、間隔に使用されると、直ちにiが呼び出される.
  • の最初のパラメータ匿名関数では、iの使用は、外部関数countSec()が終了するまでの時間が経過したため、閉パケットが形成される.
  • で呼び出されたiの値は繰り返しチェックされ、すでに11であり、コンソールは1秒おきに11の値を出力する.
  • では.必要に応じてどのように出力しますか?

    letを使用します。

    varletの差で、複文ではvarではなく、letで、自由に出力できます.letはブロックスキャンを有するので、ブロックが有する特定の変数を記憶し、その変数を参照する.

    リファレンス

  • モジュール-生活コード
  • モジュール-JavaScript-MDN Web Docs
  • settimeout例のclosure
  • [Javascript ES6] 1. ES 6(let,closure)-今日もうなずく