Reputation: 2551
Is it possible to dynamically build a function based off another functions parameters?
For example:
Base Function:
const someFunction = (functionName, functionParams) => {
// Function Built here
};
someFunction("colorFunction", ["red", true]);
I'd like it to build something similar to this: I'd need to deconstruct the Array into individual params, but I'm not sure how simple that is? And I have no idea how I'd use the first String to call the function name?
functionName(...functionParams);
Which in my head would sort of work like this:
const colorFunction = (color, bool) => {
console.log("Colour: " + color);
console.log("Bool: " + bool);
};
Bit confused by this - I feel like I'm not a million miles away, but I'm not certain! Any help would be great, thanks!!
Edit - Why?
I have a react component with a click event that fires off a redux action. Ideally this action would fire some stuff over to my reducer, and asynchronously call this "dynamic" function. I can do this with a load of if/elses, but I don't think that's a very clean way of achieving this, if building a function this way is possible.
Upvotes: 0
Views: 121
Reputation: 4062
First you need to determine where the functions you want to call dynamically are stored. If they are global functions then you can call them using window
:
const someFunction = (functionName, functionParams) => {
window[functionName]();
};
If they are methods of an object, then you can do something similar using the object:
const someFunction = (functionName, functionParams) => {
myObject[functionName]();
};
As for how to pass the arguments, you have a couple options here. If you are running a recent version of JS, or using polyfills, then you can indeed use the spread operator:
const someFunction = (functionName, functionParams) => {
window[functionName](...functionParams);
};
Otherwise you can always rely on the apply method:
const someFunction = (functionName, functionParams) => {
window[functionName].apply(null, functionParams);
};
The first argument in the apply method is the context you wish to pass to your function, in your case it doesn't seem necessary, hence the null
value.
Edit: corrected bind
with apply
as mentionned by Bergi
Upvotes: 2
Reputation: 28983
What you are looking for is Function#bind
in order to make a thunk - basically a function that takes no parameters and it's used for delayed computation.
Using .bind
you can do a partial application on a function. In your case, you would just apply all arguments and only leave the execution step at the end:
//your function
const colorFunction = (color, bool) => {
console.log("Colour: " + color);
console.log("Bool: " + bool);
};
//partially apply all argument to it
const thunk = colorFunction.bind(null, "red", true);
//this can now be passed around and executed at a later point
setTimeout(thunk, 3000);
console.log("wait 3 seconds");
Since functions are first class members in JavaScript, you can pass any function this way. If you really need a function that turns others into thunks then you can very easily do that:
const toThunk = (func, args) => func.bind(null, ...args);
Which is your someFunction
but with just the name and parameters re-named for a bit of clarity.
Upvotes: 0