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?
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?
Share Improve this question edited May 21, 2015 at 19:11 eatonphil asked May 21, 2015 at 19:06 eatonphileatonphil 13.7k30 gold badges79 silver badges141 bronze badges 3- 3 "best way" is pretty open-ended, from what perspective? – Rob M. Commented May 21, 2015 at 19:07
- 1 Right, edited. I mean most idiomatic. – eatonphil Commented May 21, 2015 at 19:08
- @eatonphil did one of the answers below help you out? – ChevCast Commented Jun 1, 2015 at 22:03
8 Answers
Reset to default 4What 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.
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]);
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.
function callEach(scope, funcs) {
funcs.forEach(function (f) { f.call(scope); });
}
callEach(this, myFunctions);
I dunno, what you have seems fine.
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);
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();});
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());
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.