2

我试图让一个函数传递一个函数并用一组参数调用它。例如:

function foo(func, args) {
  return func(args);
}

但是,我不知道 args 中可能有多少个元素,并且 func 应该能够是一个任意函数,可以接受任意数量的 args。我该如何处理?

还说我想存储传递给 foo 的函数,并且只有在之前没有调用过它们时才调用它们。

我可以做类似的事情:

var calledFuncs = [];
function foo(func, args) {
  if(calledFuncs.indexOf(func) === -1) {
    calledFuncs.push(func);
    return func(args);
  }
}

谢谢,我对 JavaScript 中的函数式编程有点陌生。

4

3 回答 3

8

您正在寻找func.apply

  • 第一个参数是上下文又名this值。你不想改变这个,所以通过它。
  • 第二个参数是一个包含参数的数组,它当然可以是动态长度的。

所以你可以这样做:

return func.apply(this, args);

你似乎对你的第二个问题有很好的方法(func(args)替换)。但是,您可能希望存储被调用函数的返回值,因为foo现在返回undefined除第一个调用之外的任何调用。

于 2012-06-08T17:35:41.563 回答
2

使用apply

func.apply(this, args);

apply将参数数组作为第二个参数。

的第一个参数apply将是this您正在调用的函数范围内的值。所以你可以传入当前的this或任何你想要的东西。

就您的第二个问题而言,这仅适用于命名函数。您可以使用func.name将函数名称存储在数组中:

var calledFuncs = [];
function foo(func, args) {
   if(calledFuncs.indexOf(func.name) === -1) {
      calledFuncs.push(func.name);
      return func(args);
   }
}

这不适用于匿名函数,也不适用于 IE 或 Opera 中的命名函数。你将不得不解析它,也许像这样:

var name = func.toString().replace(/\n/g, "").replace(/\s*\(.*$/, "").replace(/^\s*function\s+/, "");

至于你的第二个问题,你可以做你现在正在做的事情。但我认为它不适用于以下情况:

foo(function() {
}, []);

foo(function() {
}, []);

它将调用这两个函数。

于 2012-06-08T17:35:33.067 回答
1

你想要Function.prototype.apply

func.apply(this,args);

将上下文(第一个参数)设置为您想要的任何内容,包括null获取window全局(就像您在当前func(...)调用中获得的那样。

虽然与您的问题没有直接关系,但另请参阅Function.prototype.call允许您类似地设置上下文但传递显式参数的相关方法。

于 2012-06-08T17:35:23.110 回答