admin管理员组

文章数量:1404599

I'm trying to have a function that is passed a function and calls it with a set of args. For example:

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

However, I don't know how many elements might be in args, and func should be able to be an arbitrary function that takes any number of args. How do I deal with this?

Also say I wanted to store the functions passed to foo and only call them if they hadn't been called before.

Can I just do something like:

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

Thanks, I'm a bit new to functional programming in JavaScript.

I'm trying to have a function that is passed a function and calls it with a set of args. For example:

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

However, I don't know how many elements might be in args, and func should be able to be an arbitrary function that takes any number of args. How do I deal with this?

Also say I wanted to store the functions passed to foo and only call them if they hadn't been called before.

Can I just do something like:

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

Thanks, I'm a bit new to functional programming in JavaScript.

Share Improve this question edited Jun 8, 2012 at 17:39 pimvdb 155k80 gold badges311 silver badges356 bronze badges asked Jun 8, 2012 at 17:34 asutherlandasutherland 2,9694 gold badges38 silver badges51 bronze badges 2
  • 2 If there will be a lot of calledFuncs, then another (faster) solution to prevent recalling would be to put a property directly on the function as a flag. Since functions are Objects, you can add properties just like any other object. Of course the property will be accessible to any code that can access the function, so keep that in mind. – user1106925 Commented Jun 8, 2012 at 17:41
  • If it's for understanding the language and not for patibility, you can also use a WeakMap of function/called pairs. – pimvdb Commented Jun 8, 2012 at 18:43
Add a ment  | 

3 Answers 3

Reset to default 8

You're looking for func.apply:

  • the first argument is the context aka this value. You don't want to change this, so pass it through.
  • the second argument is an array containing the arguments, which can of course be of dynamic length.

So you could do this:

return func.apply(this, args);

You seem to have a fine approach to your second issue (with the func(args) replaced). You may want to store the return value of called functions, though, since foo now returns undefined for any calls except the first.

Use apply:

func.apply(this, args);

apply takes an array of arguments as the second argument.

The first argument to apply will be the value of this in the scope of the function that you are calling. So you can pass in the current this or anything else that you want.

As far as your second question goes, that will only work for named functions. You can use func.name to store the function name in your array:

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

This won't work for anonymous functions and it doesn't work for named functions in IE or Opera. You're going to have to parse it out, perhaps like so:

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

As far as your second question goes, you can do what you're doing right now. But I don't think it would work for the following case:

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

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

It will call both of those functions.

You want Function.prototype.apply:

func.apply(this,args);

Set the context (the first argument) to whatever you want, including null to get the window global (as you would get with your current func(...) invocation.

Although not directly related to your question, see also the related Function.prototype.call method that allows you to similarly set the context, but pass explicit parameters.

本文标签: javascriptPassing an array of argumentsStack Overflow