コールバック関数(コールバック)を理解する

コールバックはJavascriptで非常に重要です。 彼らはほとんどどこにでもあります。 しかし、C / Javaでのプログラミングの経験にもかかわらず、私はそれら(および非同期プログラミングのアイデアそのもの)に苦労し、それを理解することにしました。 奇妙なことですが、インターネット上のコールバック関数に関する優れた入門記事を見つけることができませんでした-主にcall()



ドキュメントの一部に出くわし、関数またはそれらの使用を示す短いコードをapply()



、今、真実を求めてバンプを入力しました、私は私は自分でコールバック関数の紹介を書くことにしました。



関数はオブジェクトです



コールバック関数を理解するには、通常の関数を理解する必要があります。 当たり前のように見えるかもしれませんが、Javascriptの関数は少し奇妙なものです。



JavaScriptの関数は、実際にはオブジェクトです。 つまり、 Function



コンストラクターによって作成されたFunction



クラスのオブジェクト。 Function



オブジェクトには、この関数のJSコードを含む文字列が含まれています。 CまたはJavaから切り替えた場合、奇妙に見えるかもしれません(コードを文字列にするにはどうすればよいでしょうか?!)が、一般的に言えば、これはJavascriptで非常に一般的です。 コードとデータの区別があいまいになる場合があります。



 //   ,    Function    var func_multiply = new Function("arg1", "arg2", "return arg1 * arg2;"); func_multiply(5, 10); // => 50
      
      







オブジェクトとしての機能の概念の利点は、通常の変数またはオブジェクトと同じ方法でコードを別の関数に転送できることです(リテラルの意味で、コードは単なるオブジェクトであるため)。



関数をコールバック関数として渡す



関数を引数として渡すのは簡単です。



 //      callback function some_function(arg1, arg2, callback) { // ,       arg1  arg2 var my_number = Math.ceil(Math.random() * (arg1 - arg2) + arg2); //       callback,     callback(my_number); } //   some_function(5, 15, function (num) { //       callback- console.log("callback called! " + num); });
      
      







通常の方法で値を返すことができる場合、このような洗練されたコードを作成するのは愚かに見えるかもしれませんが、実際的ではなく、コールバック関数が必要な状況があります。



出口を乱雑にしないでください



従来、関数は引数を入力として受け取り、 return



式を使用してreturn



ます(関数の最後にある唯一のreturn



式は、1つのエントリポイントと1つの出口ポイントです)。 それは理にかなっています。 関数は基本的に入力と出力の間のルートです。



Javascriptを使用すると、少し異なる方法で処理できます。 関数の実行が完了して値を返すのを待つ代わりに、コールバック関数を使用して非同期に取得できます。 これは、ブラウザを一時停止できないため、たとえばAJAXリクエストで完了するのに長い時間がかかる場合に役立ちます。 コールバックが呼び出されるのを待っている間、他のことを続けることができます。 実際、Javascriptですべてを非同期に実行することが非常に頻繁に要求されます(むしろ強く推奨されます)。



AJAXを使用してXMLファイルをロードし、 call()



関数を使用して、要求されたオブジェクトのコンテキストでコールバック関数を呼び出すより詳細な例を次に示します(つまり、コールバック関数内でthis



を指定すると、要求されたオブジェクト):



 function some_function2(url, callback) { var httpRequest; //   XMLHttpRequest- if (window.XMLHttpRequest) { httpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { //   Internet Explorer' httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } httpRequest.onreadystatechange = function () { //       //       if (httpRequest.readyState === 4 && httpRequest.status === 200) { callback.call(httpRequest.responseXML); //   } }; httpRequest.open('GET', url); httpRequest.send(); } //   some_function2("text.xml", function () { console.log(this); }); console.log("    ");
      
      







この例では、httpRequestオブジェクトを作成し、XMLファイルをロードします。 関数の最後に値を返すという典型的なパラダイムは、ここでは機能しなくなりました。 リクエストは非同期に処理されます。つまり、リクエストを開始し、終了するとすぐに関数を呼び出すように指示します。



ここでは、2つの匿名関数を使用します。 名前付き関数を使用することは難しくありませんが、簡潔にするために入れ子にしました。 最初の匿名関数は、httpRequestオブジェクトのステータスが変化するたびに実行されます。 ステータスが4(リクエストが完了)になり、ステータスが200(リクエストが成功)になるまでこれを無視します。 現実の世界では、リクエストが失敗したかどうかを確認したいと思いますが、ファイルが存在し、ブラウザでダウンロードできると想定しています。 この匿名関数はhttpRequest.onreadystatechangeに関連付けられているため、すぐに実行されるのではなく、リクエストの状態が変わるたびに呼び出されます。



最終的にAJAXリクエストを完了すると、コールバック関数を実行するだけでなく、これにcall()



関数を使用しcall()



。 これは、コールバック関数を呼び出す別の方法です。 前に使用したメソッド-ここから開始する単純な関数はうまく機能しますが、 call()



関数の使用を示す価値があると思いました。 別の方法として、 apply()



関数を使用することもできapply()



関数とcall()



違いについては、この記事の範囲を超えています。これは、引数が関数に渡される方法に影響するだけです)。



call()



を使用する素晴らしい点call()



、関数が実行されるコンテキストを自分で設定できることです。 これは、コールバック関数内でthis



を使用する場合、 call()



最初の引数として渡すものを指すことを意味します。 この例では、匿名関数内でこれを参照したときに、AJAXリクエストからresponseXMLを参照しました。



最後に、2番目のconsole.log式が最初に実行されます。これは、要求が完了するまでコールバック関数が実行されず、これが発生するまで、コードの後続部分が静かに実行し続けるためです。



まとめて



コールバック関数を自分のコードで使い始めるのに十分理解できたと思います。 コールバック関数に基づいてコードを構造化することはまだ困難です(最終的にはスパゲッティのように見えます...私の心は通常の構造プログラミングにあまりにも慣れています)。それらは非常に強力なツールであり、Javascript言語の最も興味深い部分の1つです。



All Articles