0

I want to be able to dynamically define variables (i.e x = 1, y = 2 - but where the user defines the names x and y, and may have a "z") - and have them be in scope when executing javascript from a string (i.e. with eval()).

Obviously, this can be done statically like so:

var x = 1, y = 2;

eval('x + y');

But I want something like this:

var context = {};

userDefinedVariables.forEach(({name, value}) => context[name] = value);

eval('x + y'); //somehow call with context

Many answers suggest concatenating strings - like eval('var ' + names[0] + ' = ' + values[0]) but that's prone to errors and code injection.

Many answers suggest modifying the global window and running eval in the global context.

How can I create a new local context for my eval execution that has access to my variable names? Something like eval().call(context)

Max Hudson
  • 9,961
  • 14
  • 57
  • 107

1 Answers1

0

This is the only way I could find to actually do this, but it does work well and reasonably concise:

var variables = [{name: 'x', value: 1}, {name: 'y', value: 2}];
var script = 'x + y';
var context = {};

variables.forEach(({name, value}) => context[name] = value);

var evaluator = Function.apply(null, [...Object.keys(context), 'script', "return eval('script = undefined;' + script)"]);

var result = evaluator.apply(null, [...Object.values(context), script]);

In the form of a helper fn:

function evalWithContext(script, context) {
  var evaluator = Function.apply(null, [...Object.keys(context), 'script', "return eval('script = undefined;' + script)"]);

  return = evaluator.apply(null, [...Object.values(context), script]);
}
Max Hudson
  • 9,961
  • 14
  • 57
  • 107