web-dev-qa-db-ja.com

JavaScriptのコールバック関数の理解を深める

関数を別の関数にコールバックとして渡して実行させることは理解していますが、それを行うための最適な実装を理解していません。私はこのような非常に基本的な例を探しています:

var myCallBackExample = {
    myFirstFunction : function( param1, param2, callback ) {
        // Do something with param1 and param2.
        if ( arguments.length == 3 ) {
            // Execute callback function.
            // What is the "best" way to do this?
        }
    },
    mySecondFunction : function() {
        myFirstFunction( false, true, function() {
            // When this anonymous function is called, execute it.
        });
    }
};

MyFirstFunctionでは、新しいcallback()を返すと、匿名関数が機能して実行されますが、それは正しいアプローチではないようです。

163
user4903

あなたは言うことができます

callback();

または、コールバック内でcallの値を調整する場合は、thisメソッドを使用できます。

callback.call( newValueForThis);

関数内のthisは、newValueForThisが何であってもかまいません。

131
krosenvold

コールバックが存在し、実行可能な関数であるかどうかを確認する必要があります。

if (callback && typeof(callback) === "function") {
    // execute the callback, passing parameters as necessary
    callback();
}

多くのライブラリ(jQuery、dojoなど)は、非同期関数に対して同様のパターンを使用し、すべての非同期関数に対してnode.jsを使用します(nodejsは通常errorおよびdataをコールバックに渡します)。彼らのソースコードを調べると助けになるでしょう!

89
arunjitsingh

関数を実行するには、主に3つの可能性があります。

var callback = function(x, y) {
    // "this" may be different depending how you call the function
    alert(this);
};
  1. callback(argument_1、argument_2);
  2. callback.call(some_object、argument_1、argument_2);
  3. callback.apply(some_object、[argument_1、argument_2]);

選択する方法は、次のいずれかによって異なります。

  1. 引数は配列に格納されるか、個別の変数として格納されます。
  2. 何らかのオブジェクトのコンテキストでその関数を呼び出したい。この場合、コールバックで「this」キーワードを使用すると、call()またはapply()で引数として渡されたオブジェクトが参照されます。オブジェクトコンテキストを渡したくない場合は、nullまたはundefinedを使用します。後者の場合、グローバルオブジェクトは「this」に使用されます。

Function.callFunction.apply のドキュメント

34
Ionuț G. Stan

コールバックはシグナルに関するもので、「新規」はオブジェクトインスタンスの作成に関するものです。

この場合、「callback();」だけを実行することがさらに適切です。とにかく戻り値で何もしていないため、「return new callback()」よりも.

(およびarguments.length == 3テストは本当に不格好で、fwiw、コールバックparamが存在し、関数であることを確認した方が良いです。)

6
annakata

適切な実装は次のとおりです。

if( callback ) callback();

これにより、コールバックパラメーターがオプションになります。

6
faeb187

次を使用できます。

if (callback && typeof(callback) === "function") {
    callback();
}

以下の例はもう少し包括的です:

function mySandwich(param1, param2, callback) {
  alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
  var sandwich = {
      toppings: [param1, param2]
    },
    madeCorrectly = (typeof(param1) === "string" && typeof(param2) === "string") ? true : false;
  if (callback && typeof(callback) === "function") {
    callback.apply(sandwich, [madeCorrectly]);
  }
}

mySandwich('ham', 'cheese', function(correct) {
  if (correct) {
    alert("Finished eating my " + this.toppings[0] + " and " + this.toppings[1] + " sandwich.");
  } else {
    alert("Gross!  Why would I eat a " + this.toppings[0] + " and " + this.toppings[1] + " sandwich?");
  }
});
2
Hasan A Yousef
function checkCallback(cb) {
  if (cb || cb != '') {
    if (typeof window[cb] === 'undefined') alert('Callback function not found.');
    else window[cb].call(this, Arg1, Arg2);
  }
}
1
Aamir Afridi

JavaScriptのcallback()関数を説明する基本的な例を次に示します。

var x = 0;

function testCallBack(param1, param2, callback) {
  alert('param1= ' + param1 + ', param2= ' + param2 + ' X=' + x);
  if (callback && typeof(callback) === "function") {
    x += 1;
    alert("Calla Back x= " + x);
    x += 1;
    callback();
  }
}

testCallBack('ham', 'cheese', function() {
  alert("Function X= " + x);
});

JSFiddle