ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptコールバック関数の詳しい解説_基礎知識

JavaScriptコールバック関数の詳しい解説_基礎知識

WBOY
WBOYオリジナル
2016-05-16 16:31:411507ブラウズ

コールバック関数の定義

コールバック関数は、関数ポインターを通じて呼び出される関数です。関数ポインタ (アドレス) をパラメータとして別の関数に渡し、このポインタがそれが指す関数を呼び出すために使用される場合、それをコールバック関数と呼びます。コールバック関数は、関数の実装者によって直接呼び出されるのではなく、特定のイベントまたは条件が発生したときに、そのイベントまたは条件に応答するために別のパーティによって呼び出されます。

JavaScript におけるコールバック関数の具体的な定義は次のとおりです。関数 A がパラメータ (関数参照) として別の関数 B に渡され、この関数 B が関数 A を実行します。関数 A をコールバック関数と呼ぶとしましょう。名前(関数式)がない場合は、匿名コールバック関数と呼ばれます。したがって、コールバックは、特定の操作の実行後にコールバック関数の実行を必要とするなど、一般的な同期 (ブロッキング) シナリオでよく使用されます。


同期 (ブロッキング) でのコールバックの使用例。その目的は、func1 コードの実行が完了した後に func2 を実行することです。

コードをコピーします コードは次のとおりです:

var func1=関数(コールバック){
//何かをします。
(コールバック && typeof(callback) === "関数") && callback();
}
func1(func2);
var func2=function(){
}

コールバック関数の使用場面
リソースのロード: js ファイルを動的にロードした後にコールバックを実行、iframe をロードした後にコールバックを実行、ajax 操作のコールバック、画像のロード完了後にコールバックを実行、AJAX など。

DOM イベントと Node.js イベントはコールバック メカニズムに基づいています (Node.js コールバックには、多層コールバックのネストに関する問題が発生する可能性があります)。
setTimeout の遅延時間は 0 です。このハックはよく使用されます。settimeout によって呼び出される関数は、実際にはコールバック

の具体化です。

連鎖呼び出し: 連鎖すると、割り当て子 (セッター) メソッド (または値自体を返さないメソッド) で連鎖呼び出しを実装するのは簡単ですが、ゲッター (ゲッター) の実装は比較的困難です。連鎖呼び出し。このポインターの代わりに必要なデータを返すためにバリューラーが必要なため、連鎖メソッドを実装したい場合は、コールバック関数を使用して実装できます。

setTimeout と setInterval の関数呼び出しは戻り値を取得します。どちらの関数も非同期であるため、つまり、呼び出しシーケンスがプログラムのメインプロセスから比較的独立しているため、本体内で戻り値を待つ方法がなく、戻り値が返されたときにプログラムが停止したり待機したりすることはありません。そうしないと setTimeout と setInterval の意味が失われるため、return を使用する意味はなく、callback のみを使用できます。コールバックの意味は、タイムリーな処理のためにタイマーの実行結果をエージェント関数に通知することです。

関数もオブジェクトです

コールバック関数を理解したい場合は、まず関数のルールを明確に理解する必要があります。 JavaScript では関数は奇妙ですが、確かにオブジェクトです。正確に言うと、関数は Function() コンストラクターを使用して作成された Function オブジェクトです。 Function オブジェクトには、関数の JavaScript コードを含む文字列が含まれています。 C または Java から来ている場合、これは奇妙に思えるかもしれません。どうしてコードが文字列になるのでしょうか?しかし、JavaScript ではこれが当たり前のことです。データとコードの区別は曖昧です。

コードをコピーします コードは次のとおりです:

//次のような関数を作成できます
var fn = new Function("arg1", "arg2", "return arg1 * arg2;");
fn(2, 3) //6
;

これを行う利点の 1 つは、コードを他の関数に渡したり、通常の変数やオブジェクトを渡したりできることです (コードは文字通り単なるオブジェクトであるため)。

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

関数をパラメータとして渡すのは簡単です。

コードをコピー コードは次のとおりです:

関数 fn(arg1, arg2, コールバック){
var num = Math.ceil(Math.random() * (arg1 - arg2) arg2);
callback(num);//結果を転送
}

fn(10, 20, function(num){
console.log("コールバックが呼び出されました! 番号: " num); });//結果は 10 から 20 までの乱数です

これは面倒、または少しばかげていると思われるかもしれませんが、通常どおりに結果を返してみてはいかがでしょうか。しかし、コールバック関数を使用する必要がある場合は、そうは思わないかもしれません。

邪魔にならないでください

従来の関数はパラメータの形式でデータを入力し、return ステートメントを使用して値を返します。理論的には、関数の最後に return ステートメントがあり、構造的には入力ポイントと出力ポイントになります。これは理解しやすいです。関数は本質的に、入力と出力の間の実装プロセスのマッピングです。

しかし、関数の実装処理が非常に長い場合、関数の処理が完了するのを待つか、コールバック関数を使用して非同期処理を行うかを選択しますか?この場合、AJAX リクエストなどのコールバック関数を使用することが重要になります。処理にコールバック関数を使用すると、コードは無駄に待つことなく他のタスクの実行を続けることができます。実際の開発では、JavaScript で非同期呼び出しがよく使用されますが、ここでも非同期呼び出しを強くお勧めします。

以下は、AJAX を使用して XML ファイルをロードし、call() 関数を使用して要求されたオブジェクトのコンテキストでコールバック関数を呼び出す、より包括的な例です。

コードをコピー コードは次のとおりです:

関数 fn(url, コールバック){
var httpRequest //XHR を作成します
httpRequest = window.XMLHttpRequest ? new XMLHttpRequest() :
window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP" ): unknown;//IE の機能検出

httpRequest.onreadystatechange = function(){
If(httpRequest.readystate === 4
&& httprequest.status === 200) {// ステータス判定
callback.call(httpRequest.responseXML); }
};
httpRequest.open("GET", url);
httpRequest.send();
}
fn("text.xml", function(){ //関数を呼び出す

console.log(this); // このステートメントの後の出力
});

console.log("これは上記のコールバックの前に実行されます。") //このステートメントが最初に出力されます


リクエストは非同期で処理されます。つまり、リクエストを開始するときに、リクエストが完了したら関数を呼び出すように指示します。実際の状況では、onreadystatechange イベント ハンドラーはリクエストの失敗の状況も考慮する必要があります。ここでは、xml ファイルが存在し、ブラウザーによって正常にロードできることを前提としています。この例では、非同期関数は onreadystatechange イベントに割り当てられているため、すぐには実行されません。

リクエストが完了するまでコールバック関数は実行されないため、最終的には 2 番目の console.log ステートメントが最初に実行されます。

上記の例は理解しにくいため、次の例を見てください。

コードをコピーします コードは次のとおりです:
関数 foo(){
var a = 10;
戻り関数(){
a *= 2;
return a; };
}
var f = foo();
f(); // 20 を返します。
f(); // 40 を返します。


関数が外部から呼び出された場合でも、変数 a にはアクセスできます。これはすべて、JavaScript のスコープが字句的であるためです。関数は、関数が実行されるスコープではなく、関数が定義されているスコープ (上記の例では foo 内のスコープ) で実行されます。 f が foo で定義されている限り、foo の実行が終了したとしても、foo で定義されたすべての変数にアクセスできます。そのスコープは保存されますが、返された関数のみがこの保存されたスコープにアクセスできるためです。ネストされた匿名関数を返すことは、クロージャを作成する最も一般的な方法です。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。