0

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.

1

2 Answers 2

3

Or something like new Function(paramNamesArray, fnBody)

Close! It would be new Function(...paramNamesArray, fnBody).

The Function constructor supports multiple arguments. The last argument is the function body. Any arguments before that are the names of the parameters.

So in your case with myParam, you'd pass "myParam: as the first argument:

const myFunc = new Function("myParam", myFnBody);

Live Example:

const myFnBody = " return myParam; ";
const myFunc = new Function("myParam", myFnBody);
const myParamVal = "Hello world.";
console.log(myFunc(myParamVal));

Going back to your paramNamesArray concept, you might do:

const myFunc = new Function(...paramNamesArray, myFnBody);

Live Example:

const myFnBody = " return myParam; ";
const paramNamesArray = ["myParam"];
const myFunc = new Function(...paramNamesArray, myFnBody);
const myParamVal = "Hello world.";
console.log(myFunc(myParamVal));


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

new Function is only the tiniest bit less of a problem than using eval. Both allow arbitrary code execution, which means both require that you fully trust the code you're evaluating with them. You don't want to take code from User A and run that code in User B's context (unless User B expressly expects and allows that, like when we click "Run code snippet" here on SO). The very minor way that new Function is slightly less problematic than eval is that it can't be used to access things in local scope, and eval can. (You can fix that by using indirect eval, which also can't use local scope.)

There are times when eval or new Function is what you need to use, but those use cases are very rare. Bottom line: If you're worried about using eval, worry about using new Function. It's (almost) just as "bad."

Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.