コアポイント
クロージング JavaScriptでは、閉鎖とは、親関数が
に戻った場合でも、親スコープ変数への参照を保持する関数です。実際には、このチュートリアルの最初の部分の変数スコープセクションで学んだように、関数に参照またはアクセスできるため、任意の関数は閉鎖と見なすことができます。
独自の関数範囲の変数とパラメーター外部(親)関数の変数とパラメーター
このコードの例では、関数は、囲まれた(親)
関数の変数とパラメーターを指します。その結果、と呼ばれると、
は、以前の変数とパラメーターを使用して「フランスのパリにいる」という正常に出力されます。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()
city
JavaScriptでは、機能は一流の市民です。この事実の結果の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); }
ステートメントの後、実際のコールバック関数、つまり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では、括弧内のすべてが式として扱われるためです。
第二に、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
window
Iifeの大きな利点の1つは、それを使用する場合、一時的な変数でグローバル空間を汚染することを心配する必要がないことです。 Iife内で定義するすべての変数はローカルになります。チェックしてみましょう:global
function showMessage(message) { setTimeout(function() { alert(message); }, 3000); } showMessage('Function called 3 seconds ago');
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
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 サイトの他の関連記事を参照してください。