Search code examples
javascriptfunctionparametersnew-operator

In javascript, how to set function parameter names when creating function via "new Function()"?


Trying to set the parameter names in a function, via new Function(fnBody), to correlate to dynamic function-body-text variables.

const myFnBody = " return myParam; ";  // dynamic fn-text, expecting 'myParam' variable.
const myFunc = new Function(myFnBody);  // create the function with the body-text.
const myParamVal = "Hello world.";  // setup argument
console.log(myFunc(myParamVal));   // output: undefined, not 'Hello world.' as desired.

console output is undefined because "myParam" isn't linked to the first argument (arguments[0]) in the function call context.

Want function to assign first arg (arguments[0]) to a "myParam" parameter, as in:

const myFunc = function (myParam) { return myParam; }

I need this for running dynamic code written with parameter-names in mind: similar to "require" and "exports" from CommonJS. The code is expecting values passed with specific parameter/variable names.

The best i've been able to come up with is to pre-set a variable via the arguments collection, then add the actual dynamic function-text:

let dynamicFnText = {SOME USER DEFINED FN BODY-TEXT, such as "return myParam;"};
let myFnBody = "";  // start the fn-body as text (string)
myFnBody += "const myParam = arguments[0];";  // prefix a parameter value via the arguments
myFnBody += dynamicFnText;  // append the dynamic fn text, which expects 'myParam' variable.

let myFunc = new Function(myFnBody);
let myParam = "Hello world.";
console.log(myFunc(myParam));  // 'Hello world."

Using eval: Yes, i could use eval(), as in:

let myFunc = eval("(function (myParam) {" + dynamicFnText + "})");  // fn with 'myParam'

However, i'm trying to avoid the "evil" eval() function. Should i not be concerned about using eval() in this manner?

I guess i was expecting some sort of .setParameters() method on the function (new Function()) instance. Or something like new Function(paramNamesArray, fnBody).

Any help appreciated. Thanks.


Solution

  • Just specify the parameter name in addition to the function body when invoking new Function:

    const myFnBody = " return myParam; ";  // dynamic fn-text, expecting 'myParam' variable.
    const myFunc = new Function('myParam', myFnBody);  // create the function with the body-text.
    const myParamVal = "Hello world.";  // setup argument
    console.log(myFunc(myParamVal));

    Since this comes from the user, make sure the user provides a list of arguments their function will accept, then list them in the new Function argument list as needed.

    Should i not be concerned about using eval() in this manner?

    No, you shouldn't - new Function is just as unsafe as eval. If you'll be using new Function, you may as well be using eval (from a security standpoint), since it allows for the execution of dynamic (and possibly unsafe) code.