6

javascript中有没有一种方法可以调用具有未知数量参数的回调?

例如,如果这是我们的调用方法:

function invokeCallback(callback, params) {
    return callback.invoke(params);
}

如果这些是我们的示例回调方法:

function action() {
    doSomeAction();
}

function greet(msg) {
    console.log(msg);
}

function nameage(name, age) {
    var msg = 'My name is ' + name + ' and my age is ' + age;
    console.log(msg);
}

如果我们可以像这样轻松地调用它们:

invokeCallback(action);
invokeCallback(greet, 'Hello!');
invokeCallback(nameage, 'Bob', 20);

那么它会很棒。

这样的事情可能吗?

4

3 回答 3

6

正如其他答案中已经提到的,Function.prototype.applyFunction.prototype.call是您要查看的两种方法。它们的操作方式略有不同 - apply 将参数作为单个数组,而 call 将它们作为单独的参数。

您可能希望探索使用此技术的相关概念是currying

关于您的示例,您应该考虑params从函数定义中删除参数并消除作为回调函数本身的开始参数:

function invokeCallback(callback) {
    var params = Array.prototype.slice.call(arguments, 1);
    return callback.apply(this, params);
}
于 2013-11-14T13:47:11.090 回答
3

是的,这是可能的。关键函数是Function#apply,它在提供上下文和参数的同时调用函数。参数以数组形式给出。(通过这种方式,它不同于Function#call,其中参数是明确给出的。)

所以让我们看看你的函数签名:

function invokeCallback(callback, params) {

我们可以很简单地做到这一点:

function invokeCallback(callback, params) {
    return callback.apply(null, params);
}

(第一个参数是函数的上下文,即其中的值this。因为我们不想指定任何特定的东西,所以我们使用null。)

但是,调用函数的方式略有不同:

invokeCallback(nameage, 'Bob', 20);

你看得到差别吗?在这里,参数是明确给出的,而不是作为数组。因此,我们需要稍微不同地处理它。在函数中,arguments对象包含提供给函数的参数。在上述情况下,它将包含三个:nameage'Bob'20。我们想nameage用参数'Bob'和调用20

arguments对象看起来像一个数组,但它不是一个。因此,我们必须使用稍微复杂的Array#slice函数调用来获取值:

var params = Array.prototype.slice.call(arguments, 1); // get all arguments after the first one

所以我们的函数看起来像这样:

function invokeCallback(callback) {
    var params = Array.prototype.slice.call(arguments, 1); // get all arguments after the first one

    return callback.apply(null, params);
}
于 2013-11-14T13:45:08.277 回答
2

callback.apply 或 callback.call

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

您的回调将如下所示:

function invokeCallback(callback, params) {
    return callback.apply(this,params);
}
于 2013-11-14T13:38:26.047 回答