Explain Codes LogoExplain Codes Logo

How to turn a String into a JavaScript function call?

javascript
functions
callbacks
promises
Anton ShumikhinbyAnton ShumikhinยทFeb 22, 2025
โšกTLDR

You can transform a string into a function call using the object bracket notation with the window object. This references a function by its name as a string. Here's a simple yet efficient example:

const yourFunc = "compute"; // insert your function's name const args = [10, 20]; // insert your arguments // Magic trick: string to function spell const stringToFunc = window[yourFunc](...args); // ๐Ÿง™โ€โ™‚๏ธ // Example function function compute(x, y) { return x + y; } console.log(stringToFunc); // Calls 'compute(10, 20)' and logs 30 ๐ŸŽฑ

This method allows you to avoid eval() and its associated risks, accessing only legitimate functions in the global scope.

Understanding different scopes and structured calls

In some scenarios, the functions might not be global, or you might need to manage structured function calls where functions are stored inside other objects. Here are several robust and secure solutions for these situations, keeping us safe from eval().

Calling nested functions with style

If your function is neatly tucked inside an object, use the dot notation or bracket notation for calling it with style:

const myNamespace = { utils: { compute: function(x, y) { return x + y; // ๐Ÿงฎ Basic calculator function, batteries included } } }; const nestedFunctionName = "utils.compute"; const args = [10, 20]; // Your own GPS system to find the function ๐Ÿ›ฐ๏ธ const segments = nestedFunctionName.split('.'); const result = segments.reduce((obj, key) => obj[key], window)(...args); console.log(result); // 30, no taxes applied

Permission to board: Verifying function's existence

Always double-check before boarding: verify that the string actually refers to a function before attempting to call it:

const isFunction = fnName => typeof window[fnName] === 'function'; if(isFunction(yourFunc)) { window[yourFunc](...args); // ๐Ÿš€ Liftoff! } else { console.error(`Houston, we have a problem. No function named ${yourFunc} exists in the global scope.`); }

Dynamic calls with a safety suit

For cases where the function names come flying at you dynamically, consider alternatives to eval() such as the Function Constructor. Do remember that although safer than eval(), it does come with its own security risks!

const sum = new Function('a', 'b', 'return a + b'); console.log(sum(2, 6)); // 8, no calculators were harmed in this operation

Juggling with parameters and this context

The complexity rises when you have to manage both the parameters and the this context of the function in the same go. Let's learn to juggle:

Using apply and call for the stage performance

For those particularly demanding, peculiar parameters or a specific this context, use the apply or call method from the function objects:

const args = [arg1, arg2, arg3]; const context = { /* a wild context appears */ }; // With apply fn.apply(context, args); // Or with call fn.call(context, ...args);

For the unexpected guest parameters

When the number of parameters is not RSVP'd, the spread operator (...) can handle those plus ones, passing the entire array as separate guests err ... arguments:

fn(...args);

For the fashionably late parameters: Currying and partial application

For those parameters that take their own sweet time to appear, you can build up the arguments over several calls aka currying or partial application:

function curriedAdd(a) { return function(b) { return a + b; }; } const addFive = curriedAdd(5); addFive(10); // 15, right on time!

Staying trendy: Best practices and security

While dynamically invoking functions can be trendy, it's equally important to remember that it comes with its own share of security concerns and maintenance overheads. So, here are some must-know best practices:

Minimalism

Dynamically creating functions can seem cool, but remember, minimalism is the key. Use a function reference instead or adopt event-driven patterns.

Cleanliness

When dealing with user inputs or data from unpredictable sources, always sanitize the inputs. A clean code is a happy code!

Restricted Access

Don't dole out access to such powerful tools to just about anyone who asks. Limit the usage to trusted parts of your codebase and avoid exposing dynamic calls to user inputs or external actors.

Use a dictionary, stay organized

Instead of directly calling a function, map function names to robust, pre-written functions using a dictionary or an object. This adds an extra layer of protection and makes your code far more manageable:

const handlers = { compute: (x, y) => x + y, subtract: (x, y) => x - y }; const handlerName = 'compute'; if(handlers[handlerName]) { handlers[handlerName](...args); // Your personal assistant, at your service! }