更好地了解JavaScript中的回调函数


163

我了解将一个函数作为回调传递给另一个函数并让其执行,但我不了解实现此目的的最佳实现。我正在寻找一个非常基本的示例,例如:

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(),则它可以工作并执行匿名函数,但这对我来说似乎不是正确的方法。


在什么意义上正确?通常,回调用于事件处理程序(最著名的是Ajax调用,它们是异步的),基本上是您不知道何时(或是否)响应的事情。
cletus

2
顺便说一句,参数是类似数组的数组,而不是array,所以您不能做arguments.length,但是可以使用slice方法将其转换为数组...
paul

1
@paul,尽管您说arguments的不是数组,但您仍然可以将其长度引用为arguments.length-试试看。此属性指的是实际传入的参数数量,而不一定是函数签名中的参数数量。
hotshot309 2011年

Answers:


132

你可以说

callback();

或者,call如果要this在回调中调整的值,则可以使用该方法。

callback.call( newValueForThis);

函数内部this将是任何东西newValueForThis


91

您应该检查回调是否存在,并且是可执行函数:

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

许多库(jQuery的,道场等)的使用为他们的异步函数对所有异步功能类似的模式,以及node.js的(通常的NodeJS传递errordata回调)。查看他们的源代码会有所帮助!


为什么要转换callback为字符串然后检查其类型?这会提高性能吗?这就像检查类型,检查转换后的布尔值是否返回true,然后再次检查其类型并针对字符串进行测试...您能解释为什么吗?
头痛

我很好奇为什么需要回调的第一个断言...是检查null还是未定义?无法typeof(callback)为您实现目标吗? typeof(null) === "Object"typeof("undefined") === "undefined"
PJH 2014年

1
短路AND。如果回调不存在,请不要费心计算其类型。虽然,你是对的。typeof()不需要它,但是我将做一个jsperf来看看短路是否值得。
arunjitsingh 2014年

@headacheCoder- callback没有被强制转换为字符串,在调用之前检查其类型以查看其是否为函数。该代码可能接受callback为参数,并且不确定该参数是可调用类型的,还是不确定该参数是各种类型,以试图提供一种多态形式,其中代码对不同的typeof参数可能会有不同的反应。
LeeGee 2014年

34

执行功能主要有3种:

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

您选择的方法取决于:

  1. 您将参数存储在数组中或作为不同的变量。
  2. 您想在某个对象的上下文中调用该函数。在这种情况下,在该回调中使用“ this”关键字将引用作为参数传递给call()或apply()的对象。如果您不想传递对象上下文,请使用null或undefined。在后一种情况下,全局对象将用于“ this”。

Docs for Function.callFunction.apply


6

回调与信号有关,“新”与创建对象实例有关。

在这种情况下,只执行“ callback();”会更加合适。而不是“返回新的callback()”,因为您无论如何都不用返回值做任何事情。

(而且arguments.length == 3测试确实很笨拙,最好检查一下回调参数是否存在并且是一个函数。)


6

正确的实现是:

if( callback ) callback();

这使回调参数成为可选。


如果callback参数不是函数怎么办?
亚基·克莱因

2

您可以使用:

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?");
  }
});


1

这是一个基本示例,解释callback()JavaScript中的功能:

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.