ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScriptの閉鎖、コールバック、IIFEの分解

JavaScriptの閉鎖、コールバック、IIFEの分解

William Shakespeare
リリース: 2025-02-20 08:43:09
オリジナル
565 人が閲覧しました

深入浅出JavaScript闭包、回调函数和立即执行函数表达式 (IIFE)

この記事では、現代のJavaScript開発における極端な3つの重要な概念を詳細に調べます:閉鎖、コールバック関数、および即時実行関数式(IIFE)。さまざまな範囲と強化について詳しく学びました。そして、探検の旅を完了しましょう。

コアポイント

    JavaScriptの閉鎖は、親機能が実行されたとしても、親機能が実行された場合でも、これらの変数を覚えて操作できる関数です。
  • コールバック関数は、他の関数にパラメーターとして渡される関数であり、外部関数内で実行され、実行を遅らせるか、非同期操作の順序を維持する方法を提供します。
  • execute now関数式(iife)は、変数の範囲を保護し、グローバルな範囲汚染を防ぐために定義の直後に実行される関数です。
  • 閉鎖は、スコープに保存されている変数を読み取りおよび更新することができ、これらの更新は、これらの変数にアクセスする任意の閉鎖に表示されます。
  • IIFEを使用すると、関数内でプライベートスコープの作成が役立ち、変数の管理を改善し、これらの変数への外部アクセスを防ぐことができます。
  • これらの概念(クロージャー、コールバック関数、IIFE)の組み合わせは、機能性をカプセル化し、グローバルな範囲汚染を回避するために、簡潔で効率的で安全なJavaScriptコードを作成するための強力なツールを提供します。

クロージング JavaScriptでは、閉鎖とは、親関数が

に戻った場合でも、親スコープ変数への参照を保持する関数です。

実際には、このチュートリアルの最初の部分の変数スコープセクションで学んだように、関数に参照またはアクセスできるため、任意の関数は閉鎖と見なすことができます。

独自の関数範囲の変数とパラメーター

外部(親)関数の変数とパラメーター
    グローバルスコープ
  • の変数
  • したがって、閉鎖を知らずに使用した可能性があります。しかし、私たちの目標は、それらを使用することだけではなく、それらを理解することです。それらがどのように機能するか理解できない場合、それらを正しく使用することはできません。これを行うために、上記の閉鎖定義を3つの理解しやすいキーポイントに分類します。
  • ポイント1:
  • 現在の関数の外側に定義された変数を参照できます。

このコードの例では、関数は、囲まれた(親)

関数の

変数とパラメーターを指します。その結果、と呼ばれると、

は、以前の変数とパラメーターを使用して「フランスのパリにいる」という正常に出力されます。
function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  printLocation();
}

setLocation("Paris"); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ポイント2:printLocation()内側関数は、外部関数が戻った後でも外部関数で定義された変数を参照できます。 setLocation()country

function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  printLocation();
}

setLocation("Paris"); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
これは、すぐに呼び出すのではなく、

printLocation()関数の外側のを除いて、最初の例とほぼ同じです。したがって、setLocation()の値は内部currentLocation関数です。 printLocation() このように思い出させる場合、<

見たように、currentLocationはその語彙範囲外で実行されます。 alert(currentLocation);は消えているようですが、

は、その変数(
function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  return printLocation;
}

var currentLocation = setLocation("Paris");

currentLocation(); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
)およびパラメーター(

)にアクセスして「覚えている」ことができます。 printLocation() setLocation()閉鎖(内部関数)は、字句範囲外で実行されている場合でも、その周りの範囲(外部関数)を覚えることができます。したがって、プログラムのいつでも後で呼び出すことができます。 printLocation() countryポイント3:city内側関数は、値ではなく、参照によって外部関数である変数を保存します。

ここで2つのクロージャーを含むオブジェクト(

)を返します。
function printLocation () {
  console.log("You are in " + city + ", " + country);
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

およびcityLocation()の現在の値が更新されます。 2回目の呼び出しの場合、デフォルトの「パリ」の代わりに、get() - "sydney"の更新(現在の)値を出力します。 set() したがって、閉鎖は保存された変数を読み取り、更新することができ、これらの更新はそれらにアクセスする任意の閉鎖に表示されます。これは、閉鎖がその値をコピーする代わりに、その外部変数cityへの参照を保存することを意味します。これを知らないことは、「すぐに機能式(IIFE)」セクションに表示されるように、これを知らないことがいくつかの発見が困難な論理エラーにつながる可能性があるためです。 get() cityの興味深い機能は、閉鎖の変数が自動的に隠されていることです。閉鎖は、直接アクセスする方法を提供することなく、囲まれた変数にデータを保存します。これらの変数を変更する唯一の方法は、間接的にそれらにアクセスすることです。たとえば、最後のコードスニペットでは、set()およびmyLocation.get()閉鎖を使用して変数を間接的に変更できることがわかります。 city

この動作を使用して、オブジェクトにプライベートデータを保存できます。データをオブジェクトの属性として保存する代わりに、コンストラクターに変数として保存し、それらの変数を参照する方法として閉鎖を使用します。

ご覧のとおり、閉鎖の周りに神秘的または深遠なものは何もありません。

callback関数get()set() cityJavaScriptでは、機能は一流の市民です。この事実の結果の1つは、関数が他の機能への引数として渡されるか、他の機能によって返される可能性があることです。

結果は高次関数と呼ばれるため、他の関数をパラメーターとしてパラメーターまたは返す関数として取得する関数、およびパラメーターとして渡される関数はコールバック関数と呼ばれます。ある時点で、それは高次関数によって「コールバック」になるため、「コールバック」と呼ばれます。

コールバック関数には、毎日多くの用途があります。そのうちの1つは、ブラウザウィンドウオブジェクトの

およびsetTimeout()メソッドを使用する場合です。これらのメソッドは、コールバック関数を受け入れて実行します。 setInterval()

別の例は、ページ上の要素にイベントリスナーを添付するときです。これを行うことにより、実際にコールバック関数へのポインターを提供します。これは、イベントが発生したときに呼び出されます。
function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  printLocation();
}

setLocation("Paris"); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

高次関数とコールバック関数がどのように機能するかを理解する最も簡単な方法は、独自の高次関数とコールバック関数を作成することです。それでは、今すぐ作成しましょう:
function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  return printLocation;
}

var currentLocation = setLocation("Paris");

currentLocation(); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ここでは、3つのパラメーターを受け入れる関数
function printLocation () {
  console.log("You are in " + city + ", " + country);
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
を作成します。これは、最初の名前と姓の2つ、コールバック関数用に1つを受け入れます。次に、

ステートメントの後、実際のコールバック関数、つまりfullName()の下に定義されているconsole.log()関数をトリガーする関数呼び出しを配置し​​ます。最後に、ここでfullName()を呼び出しますgreeting()ここで、fullName()は変数として渡されます - ブラケットなしgreeting() - - すぐに実行することは望まないので、fullName()

関数呼び出しではなく、関数定義を渡しています。これにより、コールバック関数がすぐに実行されるのを防ぎます。これは、コールバック関数の背後にある哲学と矛盾しています。関数定義として渡されると、それらはいつでも、コンテンディング機能のいつでも実行できます。さらに、コールバック関数は実際に関数内に配置されているように振る舞うため、実際に閉鎖です。関数を含む変数とパラメーターにアクセスし、グローバルスコープ内の変数にアクセスできます。

コールバック関数は、既存の機能(前の例に示すように)または匿名関数を作成する場合があります。

コールバック関数は、汎用性と再利用性を提供するために、JavaScriptライブラリで広く使用されています。ライブラリメソッドの簡単なカスタマイズおよび/または拡張を可能にします。さらに、コードはメンテナンスが簡単で、より簡潔で読みやすいです。コールバック関数は、不必要な重複コードパターンをより抽象的/一般的な関数に変換する必要がある場合に役立ちます。
function cityLocation() {
  var city = "Paris";

  return {
    get: function() { console.log(city); },
    set: function(newCity) { city = newCity; }
  };
}

var myLocation = cityLocation();

myLocation.get(); // 输出:Paris
myLocation.set('Sydney');
myLocation.get(); // 输出:Sydney
ログイン後にコピー
ログイン後にコピー

2つの関数が必要だとします。1つは公開された記事情報を印刷し、もう1つは送信されたメッセージ情報を印刷するものです。それらを作成しましたが、ロジックの一部が両方の機能で繰り返されていることに気付きました。同じコードを1つの場所に置くことは不要であり、維持するのが難しいことを知っています。それで、解決策は何ですか?次の例で説明しましょう:

function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  printLocation();
}

setLocation("Paris"); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ここで行うことは、重複したコードパターン(

およびconsole.log(item))を別の一般関数(var date = new Date())に配置し、特定のデータのみを他の機能に保持することです。これらは、関数がコールバック関数になります。このようにして、同じ関数を使用して、メッセージ、記事、本、雑誌など、さまざまな関連するものに関する関連情報を印刷できます。あなたがする必要がある唯一のことは、各タイプの特別なコールバック関数を作成し、それをpublish()関数の引数として渡すことです。 publish()

function式式をすぐに実行(iife)

関数式をすぐに実行するか、iife(「ify」と発音)は、作成後すぐに実行される関数式(名前または匿名)です。

このモードにはわずかに異なる構文バリアントが2つあります。

通常の関数をiifeに変換するには、2つのステップを実行する必要があります。
function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  return printLocation;
}

var currentLocation = setLocation("Paris");

currentLocation(); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ブラケットに関数全体を囲む必要があります。名前が示すように、Iifeは関数定義ではなく関数式でなければなりません。したがって、括弧を囲む目的は、関数の定義を式に変換することです。これは、JavaScriptでは、括弧内のすべてが式として扱われるためです。

    最後にブラケットを追加する(バリアント1)、またはブレースを閉じた後(バリアント2)、関数がすぐに実行される必要があります。
  1. 覚えておくべき3つのこと:
まず、変数に関数を割り当てる場合、括弧内に関数全体を囲む必要はありません。

第二に、Iifeはセミコロンで終了します。そうしないと、コードが適切に機能しない場合があります。

第三に、次の例に示すように、パラメーターをiifeに渡すことができます(結局、それは関数です):
function printLocation () {
  console.log("You are in " + city + ", " + country);
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

グローバルオブジェクトをiifeのパラメーターとして渡すことは、ブラウザ環境から独立したコードを使用することなく、関数内にアクセスするための一般的なパターンです。次のコードは、使用しているプラ​​ットフォームに関係なく、グローバルオブジェクトを参照する変数

を作成します。

このコードは、ブラウザ(グローバルオブジェクトは

)またはnode.js環境(グローバルオブジェクトを参照するために特別な変数
function cityLocation() {
  var city = "Paris";

  return {
    get: function() { console.log(city); },
    set: function(newCity) { city = newCity; }
  };
}

var myLocation = cityLocation();

myLocation.get(); // 输出:Paris
myLocation.set('Sydney');
myLocation.get(); // 输出:Sydney
ログイン後にコピー
ログイン後にコピー
を使用しています)で動作します。

windowIifeの大きな利点の1つは、それを使用する場合、一時的な変数でグローバル空間を汚染することを心配する必要がないことです。 Iife内で定義するすべての変数はローカルになります。チェックしてみましょう:global

この例では、最初の
function showMessage(message) {
  setTimeout(function() {
    alert(message);
  }, 3000);
}

showMessage('Function called 3 seconds ago');
ログイン後にコピー
ステートメントは正常に機能しますが、変数がIIFEによる局所変数になるため、2番目のステートメントは失敗します。

window閉鎖は外部変数への参照を保持しているため、最新/更新された値を返すことがすでにわかっています。それで、あなたは次の例の出力は何だと思いますか? global

function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  printLocation();
}

setLocation("Paris"); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

果物の名前は、秒間に1つずつ印刷されると予想される場合があります。ただし、実際、出力は「未定義」の4倍です。それで、問題は何ですか?

問題は、

ステートメントでは、ループの各反復に対してconsole.log()の値が4に等しいことです。また、i配列のインデックス4には何もないため、出力は「未定義」です。 (JavaScriptでは、配列のインデックスが0から始まることを忘れないでください。)fruitsが4に等しい場合、ループは終了します。 i この問題を解決するには、ループによって作成された各関数の新しい範囲を提供する必要があります。これを行います。Iifeの

メソッドをオフにし、プライベート変数を定義して現在のコピーを保持します。

i setTimeout()同じタスクを実行する次のバリアントを使用することもできます。 i

iifeは通常、モジュールをカプセル化するためのスコープを作成するために使用されます。モジュール内には、偶発的な変更を防ぐ自己完結型のプライベートスコープがあります。この手法はモジュールパターンと呼ばれ、JQueryやUnderscoreなどの多くの最新のJavaScriptライブラリで広く使用されている閉鎖管理スコープを使用する強力な例です。
function setLocation(city) {
  var country = "France";

  function printLocation() {
    console.log("You are in " + city + ", " + country);
  }

  return printLocation;
}

var currentLocation = setLocation("Paris");

currentLocation(); // 输出:You are in Paris, France
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

結論
function printLocation () {
  console.log("You are in " + city + ", " + country);
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

このチュートリアルの目的は、これらの基本概念を、可能な限り明確かつ簡潔に紹介することです。これは、原則またはルールの単純なセットとしてです。それらをよく理解することは、成功した効率的なJavaScript開発者になるための鍵です。

ここで説明したトピックを詳細かつ詳細に説明するために、カイルシンプソンの「You Do n't not JS:Scopes and Crocures」を読むことをお勧めします。

(後続のコンテンツ、すなわちFAQパーツは、記事の長さのために省略されています。必要に応じて、具体的な質問をしてください。)

以上がJavaScriptの閉鎖、コールバック、IIFEの分解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート