#関連する学習に関する推奨事項:まえがき
# 終わりに は、フロントエンド開発者にとって常に回避できないハードルであり、好むと好まざるにかかわらず、仕事や面接で遭遇することがあります。クロージャについての理解は人それぞれ異なりますので、ここでは私自身のクロージャについての理解をお話します。 (理解に矛盾がある場合は、ご自身でご参照ください)
クロージャの定義方法定義を与える前に、他の人がどのようにクロージャを定義しているかを見てみるとよいでしょう:関数オブジェクトはスコープ チェーンを通じて相互に関連付けることができ、関数本体内の変数は関数スコープに保存できます。この機能は、コンピュータ サイエンスの文献では「クロージャ」と呼ばれています - JavaScript オーソリティ ガイド (第 6 版)
#クロージャは、別の関数のスコープ内の変数にアクセスできる関数です。クロージャを作成する一般的な方法は、別の関数の中に関数を作成することです。 --Advanced Programming in JavaScript (Third Edition)
関数が現在の字句スコープ内にある場合でも、関数がその字句スコープを記憶してアクセスできる場合、クロージャが発生します。ドメインの外。 -- あなたの知らない JavaScript (第 1 巻)上記の段落の説明は同じではありませんが、注意深く味わってみると、いくつかの共通点を見つけることができます。これらの中で最も重要なのは、異なるスコープ間の
接続 です。もちろん、上記の定義を直接引用することもできます (結局のところ、上記の定義は比較的信頼できるものです)。ここでは、著者は最後の段落の定義を好み、書籍「あなたが知らない JavaScript (第 1 巻)」を強く推奨します。 、注意深く繰り返し読む価値があります。
クロージャにどのようなナレッジ ポイントが関係しているか定義を与えるだけでは十分ではなく、どのようなナレッジ ポイントが内部的に関係しているのかも調査する必要があります。筆者が役立つと思った知識を以下に挙げます。 スコープとスコープ チェーン実は、著者は皆さんがこれについて考えたことがあることを知っています (いいえ、これを考えたことがない人は誰もいません)。これで誰もがscope を知ることができました。ここではそれを簡単に説明し、そのプロセスを見ていきます。
スコープ: 変数を名前で検索するための一連のルール。グローバルスコープ、関数スコープ、ブロックスコープの3種類に分かれます。注目すべきはES6の新しい仕様であるブロックスコープです。中括弧
{} 内の
let および const を使用して定義された変数はスコープにバインドされ、中括弧の外側からはアクセスできません。
注: 中括弧の先頭と let 変数宣言の前の間に 一時的なデッド ゾーンがあります (この点はこの記事の範囲外です) 。 スコープ チェーン: 異なるスコープが一緒にトラップされると、スコープ チェーンが形成されます。検索方向は内側から外側であることに注意してください。
スコープの検索方向が内側から外側になるのはなぜですか?これは興味深い質問です。個人的には、js の実行関数がスタックにプッシュされる方法によって決まると思います (少し話が逸れたように感じます。興味のある友人は情報を確認してください)。 字句スコープ
関数が別の関数スコープ内の変数にアクセスできる (または現在のスコープを覚えていて、現在のスコープの外にアクセスできる) 理由の重要なポイント
はプログラミングの世界には、スコープの 2 つの作業モードがあります。1 つは、ほとんどのプログラミング言語で使用される
字句スコープ で、もう 1 つはその逆です。
ダイナミック スコープ
それ以外の場合は、例を挙げてみましょう:
字句スコープ: 変数とブロックのスコープはコードを書くときに決定され、オブジェクトや呼び出される場所によって変更されません (これは反対)。
let a = 1; function fn(){ let a = 2; function fn2(){ console.log(a); } return fn2; } let fn3 = fn(); fn3();
上記の定義から、fn3 ## であることがわかります。fn
はクロージャ関数
#fn2
のポインタ アドレスを取得しました。fn3 が実行されると、実際には
fn2 が実行され、内部の
a 変数は、スコープ チェーンの検索ルールでは、検出されるのは
fn スコープ内の変数
a であるため、最終出力は 1 ではなく 2 になります。 (下の図をご覧ください)
話は逸れますが、字句スコープを欺くにはどうすればよいでしょうか?