8

What is the most idiomatic way to call all functions in a list?

The best I can think of is:

myFunctions.forEach(function(f){f();});

Is there a more idiomatic way of doing this?

EDIT:

I'm really only interested in ES5 for now. Perhaps there is some way having to do with Array prototypes?

3
  • 3
    "best way" is pretty open-ended, from what perspective? Commented May 21, 2015 at 19:07
  • 1
    Right, edited. I mean most idiomatic. Commented May 21, 2015 at 19:08
  • @eatonphil did one of the answers below help you out? Commented Jun 1, 2015 at 22:03

8 Answers 8

4

What about ES6? You can use arrow function.

This would be :

myFunctions.forEach( f => f());

You can already use it today with tool like babel. For an overview of ES6 features check out es6features.

EDIT:

You can extend the Array object with the following method:

Array.prototype.invokeFunctions = function () {
    this.forEach(function (f) {
    if (typeof(f) === "function")
      f()
    });
}

var functions = [
    function () { console.log(1);},
    function () { console.log(2);}
];

functions.invokeFunctions();
// output 
1
2

However, I don't think this is a good idea as it pollutes the global Array prototype. A better idea could be to use an object designed explicitly for this purpose. For example:

function FunctionList(functions) {
  this.functions = functions;
}

FunctionList.prototype.callAll = function () {
  this.functions.forEach(function (f) {
    if (typeof(f) === "function")
      f()
  });
}

var functionList = new FunctionList(functions);
functionList.callAll();

This is a better solution in my opinion. Every time you have a function array you can wrap it in a FunctionList object. However in this case you lose all the benefits of using an Array and you have to implement getter and setter methods if you want to modify/access the function array.

Sign up to request clarification or add additional context in comments.

Comments

2

You could get tricky and use prototype methods, though it's not much more succinct:

myFunctions.map(Function.prototype.call, Function.prototype.call);

a wee bit shorter if you grab a reference to call:

var call = Function.prototype.call;
myFunctions.map(call, call);

or we could go nuts with prototype methods:

[].map.apply(fns, [call, call]);

Comments

1

Well you didn't say we couldn't use es6 arrow functions ;)

funcs.forEach(x => x());

If you can't use es6, you can always use Babel.

Comments

1
function callEach(scope, funcs) {
  funcs.forEach(function (f) { f.call(scope); });
}

callEach(this, myFunctions);

I dunno, what you have seems fine.

Comments

1

This seems like the perfect use of forEach. Apart from ES6, the only thing I would do differently is pull out the function for readability:

var callSelf = function(funcToCall) {
    funcToCall();
}

Because then I can run:

myFunctions.forEach(callSelf);

1 Comment

Wouldn't call be the best choice
0

Depends on if you need the results or only side-effects. Here's with capturing the return values:

var results = fns.map(function(fn){return fn();});

1 Comment

The reason why I say this is because foreeach doesn't work well with promises
0

Here's some creative code, basically shifting the responsibility of determining which functions need to be called to the function itself.

function c() {
    console.log("c");
}

function b() {
    console.log("b");
    return c;
}

function a() {
    console.log("a");
    return b;
}

for(var f = a; f instanceof Function; f = f());

Comments

0

Hm i use for-in for arrays, not for objects (beware).

var ts = [function (){alert('a');}, function (){alert('b');}];
for (var tsIndex in ts) ts[tsIndex]();

Will alert a and b.

Beware: Do it with array only.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.