How to execute a JavaScript function when I have its name as a string ?

To execute a JavaScript function when you have its name as a string, follow these steps:

1. Basic Global Function

If the function is globally accessible (e.g., defined in the global scope or attached to window in browsers):

// Define a global function
function greet(name) {
  console.log(`Hello, ${name}!`);
}

// Function name as a string
const functionName = "greet";

// Execute the function
window[functionName]("Alice"); // Output: "Hello, Alice!"

2. Nested Object Function

If the function is nested inside an object (e.g., myObj.utils.sayHello):

const myObj = {
  utils: {
    sayHello: function(name) {
      console.log(`Hello, ${name}!`);
    }
  }
};

// Function path as a string
const functionPath = "utils.sayHello";

// Split the path into parts and resolve the function
const pathParts = functionPath.split('.');
const context = myObj; // Starting context (myObj)
const func = pathParts.reduce((obj, key) => obj?.[key], context);

// Execute the function if it exists
if (typeof func === "function") {
  func("Bob"); // Output: "Hello, Bob!"
}

3. Generic Helper Function

Create a reusable function to resolve and execute any function by name:

function executeFunctionByName(functionName, context, ...args) {
  const pathParts = functionName.split('.');
  let currentContext = context || window; // Default to global (window)

  // Traverse nested properties (e.g., "myObj.utils.sayHello")
  for (const part of pathParts) {
    currentContext = currentContext[part];
    if (!currentContext) {
      throw new Error(`Path "${functionName}" not found.`);
    }
  }

  if (typeof currentContext !== "function") {
    throw new Error(`"${functionName}" is not a function.`);
  }

  // Call the function with its original context and arguments
  return currentContext.apply(context, args);
}

Usage:

// Example 1: Global function
executeFunctionByName("greet", window, "Alice"); // "Hello, Alice!"

// Example 2: Nested function
const myObj = {
  utils: {
    log: function(message) {
      console.log(`Log: ${message}`);
    }
  }
};
executeFunctionByName("utils.log", myObj, "Success!"); // "Log: Success!"

4. Edge Cases

Functions in Modules

For functions in modules (ES6/CommonJS), ensure they are exported and accessible via an object:

// myModule.js
export const utils = {
  logError: (msg) => console.error(`Error: ${msg}`)
};

// Usage in another file
import * as myModule from './myModule.js';
executeFunctionByName("utils.logError", myModule, "File not found!");

Handle Asynchronous Functions

For async functions, use await:

const asyncFunc = {
  fetchData: async (url) => {
    const res = await fetch(url);
    return res.json();
  }
};

// Execute
executeFunctionByName("fetchData", asyncFunc, "https://api.example.com")
  .then(data => console.log(data));

Key Considerations

  1. Scope: The function must be accessible via the provided context (e.g., window for global functions).
  2. Security: Avoid using eval() (e.g., eval("greet('Alice')")) due to security risks.
  3. Error Handling: Check if the resolved path is a function before calling it.
  4. Context Binding: Use apply() or call() to preserve the function’s this context.

Summary

ScenarioCode Example
Global functionwindow['functionName'](...args)
Nested object functionexecuteFunctionByName("obj.func", context)
Module functionPass the module as the context
Async functionawait executeFunctionByName(...)

This approach safely resolves and executes functions by name while preserving their context.

Leave a Reply

Your email address will not be published. Required fields are marked *