ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript クロージャ - 匿名関数と関数のスコープ チェーン

JavaScript クロージャ - 匿名関数と関数のスコープ チェーン

黄舟
黄舟オリジナル
2017-01-20 14:15:131463ブラウズ

匿名関数

JavaScript クロージャを理解する前に、JavaScript における関数の実行順序を理解する必要があります。前に述べたように、関数を定義するにはさまざまな方法がありますが、最も一般的なのは次の 2 つの方法です。

/* 定义函数的第一种方式 */
function fn1(){
  alert("fn1");
}
/* 定义函数的第二种方式 */
var fn2 = function(){
  alert("fn2");
}

関数を定義する最初の方法は、関数宣言と呼ばれます。この方法で宣言された関数は、関数が実行される前にメモリにロードされるため、関数が定義される前でも後でも、関数が呼び出されてもエラーは報告されません。

関数を定義する 2 番目の方法では、それを関数式と呼びます。このように定義された関数は、最初にメモリ内に領域を作成し、次に fn2 変数を通じてこの領域を指します。この種の関数は最初は名前がありません。これは匿名関数とも呼ばれます。ラムダ関数。関数を作成する前に fn2() を呼び出すと、プログラムはエラーを報告します。

関数スコープチェーン

JavaScript では、関数が呼び出されるときに実行環境が作成され、属性 SCOPE が各関数に追加されます。この属性は、すべてのコンテキストの変数を含むメモリの一部を指します。ある関数内で新しい関数が呼び出されるとき、新しい関数は元の関数の SCOPE と新しく追加された SCOPE を実行するスコープを持ち、チェーン構造を形成します。これが JavaScript チェーンのスコープです。

各関数には独自の実行環境があります。実行フローが関数に入ると、関数の環境が環境スタックにプッシュされます。関数の実行が完了すると、スタックはその環境をポップし、制御を元の実行環境に戻します。

スコープ チェーンの目的は、実行環境がアクセスできるすべての変数と関数への順序付けされたアクセスを保証することです。スコープ チェーンの先頭には常に、現在実行中のコードが配置されている環境の変数オブジェクトが配置されます。スコープ チェーン内の次の変数オブジェクトは包含環境から取得され、次の変数オブジェクトは次の包含環境から取得され、グローバル実行環境に継続されます。グローバル実行環境の変数オブジェクトは、常にスコープ チェーンの最後のオブジェクトになります。

上記の段落は何を意味しますか?具体例とメモリモデル分析を通して解説していきます。まず次の例を見てみましょう。次の例の機能は、単純に color 属性の色を交換することです。

// 定义一个颜色属性
var color = "red";
 
// 定义显示颜色的方法
var showColor = function(){
  console.info(this.color);
} 
 
/* 定义一个交换颜色的函数 */
function changeColor(){
  var anotherColor = "blue";
  function swapColor(){
    var tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;
  }
  swapColor();
}
 
// 调用交换颜色的函数来改变颜色
changeColor();
 
// 调用showColor()方法
showColor();

上記のコードを見てみましょう。まず、カラー変数 color と、印刷用のカラー変数を定義します。メソッド showColor()。次に、色を交換する関数changeColor()が定義されます。その機能は、グローバル スコープ内の色「赤」を「青」に変更することです。この関数では、交換は別の関数 swapColor() を通じて実装されることに注意してください。

次に、changeColor() 関数の実行を開始します。上で述べたように、js が関数を実行すると、実行環境が作成され、各関数に SCOPE 属性が追加されます。この属性は、すべてのコンテキスト変数を含むメモリを指します。次に、changeColor() 関数を実行すると、メモリ モデルは次の図のようになります。

JavaScript クロージャ - 匿名関数と関数のスコープ チェーン


図の青い部分は、changeColor() 関数のスコープ チェーンです。 changeColor() のコンテキストは window オブジェクトであるため、そのスコープ チェーンの最上位ビットはグローバル スコープを指します。私たちのプログラムには現在、グローバル スコープ内に color、showColor、changeColor の 3 つのプロパティがあります。

changeColor() スコープ チェーンの下位ビットは、独自のスコープを指します。 changeColor() には、anotherColor と swapColor の 2 つの属性があります。

次に、changeColor()関数が実行され、関数内にswapColor()関数が作成されます。この関数は作成直後に実行されます。このときのスコープチェーンのメモリモデルは下図のようになります

JavaScript クロージャ - 匿名関数と関数のスコープ チェーン

同様に、swapColorスコープチェーンの上端はグローバルスコープを指し、次のレベルは以下を含むchangeColor関数のスコープを指します。最後に、それ自体を指すスコープです。

その後、swapColor 関数が実行を開始します。最初のコードは var tempColor = anotherColor です。上の図によると、tempColor が swapColor のスコープ内に存在することがわかります。属性を変更するため、tempColor の値が「赤」から「青」に変更されます。

コードの 2 番目の文は、anotherColor = color です。まず、swapColor のスコープ内で anotherColor 属性も検索します。見つからない場合は、スコープ チェーンを介して上位レベルのchangeColor まで検索します。スコープが見つかると、anotherColor 属性が「青」から「赤」に変更されます。

コードの 3 番目の文は color = tempColor です。属性の検索方法は同じです。見つからない場合は、上位のスコープに移動して検索します。最終的に color 属性がグローバル スコープで見つかるため、グローバル スコープの color 属性が「red」から「blue」に変更されます。

最後に、swapColor関数が実行された後、関数はガベージコレクションされます。同時にchangeColor関数も実行され、ガベージコレクションが行われます。次に、showColor() メソッドを呼び出します。これにより、関数の新しい実行環境とスコープ チェーンが作成されます。

showColor のスコープ チェーンには、トップレベルのグローバル スコープと独自のスコープという 2 つのポイントがあります。 showColor 関数を実行すると、自身のスコープでは color 属性が見つからないため、上位のグローバル スコープで検索します。このとき、グローバル スコープの color 属性は「blue」に変更されています。プログラム 最終的に印刷される色は「青」です。

上記は JavaScript クロージャーの内容です。匿名関数と関数スコープ チェーンの詳細については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。