JavaScript閉鎖を理解する



それは本当に理解するのが難しい概念でした、そして、閉鎖が何であるかについて理解するために、私はしばらくかかりました.したがって、ここではより良い可視化のためのダイアグラムとコードスニペットとは何かの私の理解です
私の脳を暖めるために、私はクロージャを含まない例を始めます、そして、最後に閉鎖を含む私の例をゆっくり変えます
function add1(){
  var x = 1;
  var f = function(y){
    return x + y;
  }
  return f(3);
}

console.log(add1());
ここでは、単純な関数add1 .
  • ローカル変数x の値1
  • もう一つの変数f 関数の指定
  • このadd1 関数は関数を返すf
  • それで、我々がこのコードを実行するならば、それは戻ります4 with x = 1およびy = 3
    関数宣言を持ち、その関数がコンソールに呼び出されます.ログ.実行コンテキストは次のようになります.

    まず第一に、我々はglobal execution context 作成中.私たちはcreation and execution フェーズ.にcreation フェーズ、我々はホイストadd1 スコープの上部とexecution フェーズを実行するadd1 機能
    呼び出しadd1 関数は作成するadd1 実行コンテキストは以下のようになります.

    この実行コンテキストでは、変数をホイストしますx and fcreation フェーズとその両方はcreation フェーズ.にexecution フェーズx1 and f が引数を受け入れる関数に割り当てられますy . 割り当て後、関数コールを返すf(3) ;

    これはFと呼ばれる別の実行コンテキストを作成しますf 実行コンテキストは、宣言された変数や関数が存在しないため、作成段階では何も上げません.実行段階では戻りますx+y の値x は、add1 実行コンテキストとy が渡されるf(3)総合的にx is 1 and y is 3 . 帰着4 . 各ECが実行された後、スタックは1つずつスタックからポップされる.
    スコープチェーンを見てみましょう

    f 実行コンテキスト、x+y . 値y この文脈ではすぐに利用可能です3 しかし、値x がない.したがって、外部実行コンテキストを参照し、x1 .
    Phewそれは大丈夫だった.うまくいけば、実行コンテキストとスコープを把握することができます.それで今、我々は閉鎖に関連している少し複雑な何かに移動する準備ができています.ここにコードスニペットがあります
    var add = function() {
      var x = 1;
      var f = function(y) {
        return x + y;
      };
      return f;
    };
    
    var g = add();
    console.log(g(3));
    
    この例では、関数への参照を返します.関数のスコープ外の関数を呼び出しますaddg(3) が呼ばれる.おそらく、この部分は把握するのが難しいかもしれません.
    では、実行コンテキストをもう一度実行し、これがどのように追加されるかを見ましょう.グローバル実行コンテキスト

    続いてadd 実行コンテキスト

    今面白い部分です.一度add 実行コンテキストの終了を実行します.

    次にG ( 3 )実行コンテキストになります.変数を覚えておいてくださいg 機能を含むf それはadd 関数.

    So gx + y .走っているg(3) だから価値y 3になります.
    の値はx ?
    よく、我々が見回すならば、我々は見つけることができませんx . でも覚えているx1 作成され、実行され、ポップされた別の実行コンテキストで.
    それでJavascript , 関数が他の関数の中で作成された場合g . So g の場合、囲む関数のスコープにある変数への参照を保持しますadd . だから意味g は、add と変数x .

    基本的にはadd 実行コンテキストは終了しましたがg はまだ実行コンテキストの変数にアクセスすることができるadd .
    機能g まだスコープチェーンを登ることができますx 実行スタックではありませんが、もう.g's 実行コンテキストclosed in x を返します.x's 実行コンテキストがなくなりました.だから我々の機能gclosure .
    のようなクロージャg 関数は内部変数を参照する.
    スコープチェーンを見てみましょう

    グローバル実行コンテキストスコープがあります.私たちはadd and g 変数と実行コンテキスト.
    アフターラインvar g = add(); 終了すると、追加実行コンテキストがスタックからポップされます.(この理由で陰影をつけられている)
    そして、g 実行コンテキスト.それはまだ参照できるようになりますx 外部変数x's 実行コンテキストはスタック上にありません
    閉じるこの動画はお気に入りから削除されています.あなたがまだ混乱しているならば、以下のリファレンスを読んでください.
    ここでは、私はこのトピックについてさらに理解するために使用する主な参照です
    Ultimate guide to execution context