ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScriptコールバック関数の定義と使用例を詳しく解説

JavaScriptコールバック関数の定義と使用例を詳しく解説

伊谢尔伦
伊谢尔伦オリジナル
2017-07-25 13:26:562100ブラウズ

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

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


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

var func1=function(callback){
    //do something.
    (callback && typeof(callback) === "function") && 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

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

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

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

function fn(arg1, arg2, callback){
    var num = Math.ceil(Math.random() * (arg1 - arg2) + arg2);
    callback(num);//传递结果
}
fn(10, 20, function(num){
   console.log("Callback called! Num: " + num); 
});//结果为10和20之间的随机数

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

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

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

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

function fn(url, callback){
    var httpRequest;    //创建XHR
    httpRequest = window.XMLHttpRequest ? new XMLHttpRequest() :   
        window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP"             ) : undefined;//针对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("this will run before the above callback.");  //此语句先输出

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

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

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

function foo(){
    var a = 10;
    return function(){
        a *= 2;
        return a;       
    };   
}
var f = foo();
f(); //return 20.
f(); //return 40.

  函数在外部调用,依然可以访问变量a。这都是因为javascript中的作用域是词法性的。函数式运行在定义它们的作用域中(上述例子中的foo内部的作用域),而不是运行此函数的作用域中。只要f被定义在foo中,它就可以访问foo中定义的所有的变量,即便是foo的执行已经结束。因为它的作用域会被保存下来,但也只有返回的那个函数才可以访问这个保存下来的作用域。返回一个内嵌匿名函数是创建闭包最常用的手段。

以上がJavaScriptコールバック関数の定義と使用例を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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