How to pass object as scope to eval?

javascript eval pass object
javascript eval alternative
javascript safe eval
js eval
pass this to eval
eval can be harmful
javascript string to function without eval
javascript expression evaluator

I've a javascript object like the following:

var myobj = {
    'a': 10, 'b': 20
}

I've a condition stored in a string like the followin:

var c = 'a==10';

I want to evaluate whether the condition in c is true or false. The variables referred in the condition string e.g. a is a member of myobj.

I've tried the following but it didn't help.

eval.call(myobj, 'a==10');

You should really question why you want to use dynamic JS content like that. If the value for c is provided by users then you need to sanitise that input before using it in eval. There are almost always better alternatives.

Therefore the solution I now propose is really enforcing a bad practice -- and not available in strict mode:

var res = eval('with (myobj) ' + c);

Or, depending how you get the info about myobj, this may be easier/more difficult:

with (myobj) var res = eval(c);

So now let's look at some safer ways. Instead of working with such values of c, build a structure of expressions that you allow. For instance:

var c = { prop: "a", operation: "equal", constant: 10 };

... and then do something like this:

var operations = {
    equal(a, b) => a == b,
    // define other operations here ...
};

function test(obj, c) {
    return operations[c.operation](obj[c.prop], c.constant);
}

Specify scope for eval() in JavaScript?, That instance of eval will use the scope of its containing function, which is nested scope.eval, 'var x = 4') log("X in the scope object should raise 'x not defined'  Notice c: new Date() in the evaluated object. In the function without the eval(), the object is being evaluated in the global scope, so it is safe for the browser to assume that Date refers to window.Date() instead of a local variable called Date.

Here's my attempt at a super hacky solution to this problem using the Function constructor (written in ES2015):

const context = {
  a: 10,
  b: 20,
};

const expression = 'a==10';

const getAllMatches = (pattern, string) =>
      // make sure string is a String, and make sure pattern has the /g flag
      String(string).match(new RegExp(pattern, 'g'));

// this pattern is far from robust
const variablePattern = /[a-zA-Z$_][0-9a-zA-Z$_]*/;

const evalWithContext = (context, expression) => {
  const variables = getAllMatches(variablePattern, expression);

  // function and arguments are keywords, so I use abbreviated names
  const func = new Function(...variables, `return (${expression})`);

  const args = variables.map((arg) => (Object.hasOwnProperty.call(context, arg)
                                       ? context[arg]
                                       : undefined));

  return func(...args);
};

console.log(evalWithContext(context, expression));

eval(), JavaScript Demo: Standard built-in objects - eval() uses local scope, result is 6 var geval = eval; // equivalent to calling eval in the global scope JavaScript has first-class functions, which means you can pass functions as  Getting Started With ASP.NET Core MVC Application; Setup and Installation ASP.NET Core 1.0; Understanding ASP.NET Core 1.0; Customize User Profile Info in MVC With ASP.NET Identity

So dirty :D

var myobj = {
    'a': 10,
    'b': 20
}

var c = 'a==10';

var res = (function() {
  return eval('this.' + c + ';');
}).apply(myobj);

console.log(res);

// or as onliner

var res2 = ((o) => eval('o.' + c)).call(null, myobj);
console.log(res2);

Functions, To use a function, you must define it somewhere in the scope from which you wish to call it. If you pass an object (i.e. a non-primitive value, such as Array or a to create functions from a string at runtime, much like eval() . But because we choose to pass in a variable declaration in the form of a string and eval will run it on line four, it cheats it and it pretends that that line of code had existed at compile time. [00:01:04] So in a sense what it does is it modifies the existing lexical scope of foo to add a new declaration to it at runtime.

Chapter 17: Dynamic evaluation, Moreover, as mentioned a little in the previous chapter, when you pass a `Proc` lvar = "toplevel lvar" # a local variable to confirm this scope obj = Object.new  An object bar is created with a single method changeFoo which does an eval. The eval creates a local variable (thanks to the var) foo, and sets it's value to 456. bar.changeFoo is called, and the value of the global foo is alerted. The aim is to test the scope in which eval runs. If eval is in the global scope, the global variable foo should change it's value.

eval - Manual, A return statement will immediately terminate the evaluation of the code. The code will be executed in the scope of the code calling eval(). Thus any variables​  You can execute eval with a particular context, where this === theContext you pass in ({ neek: true } for example). The trick is you have to .call another function which then calls eval , you cannot .call eval directly and accomplish this as in your example.

Evaluating JavaScript code via eval() and new Function(), var a = 12; > eval('a + 5') 17. Note that eval() parses in statement context [1]: > eval('{ foo: 123 }') // code block 123 > eval('({ foo: 123 })') // object  c = MyObj() c.eval("func1(42)+func2(24)") in Python..i.e. have func1() and func2() be evaluated within the scope of the object 'c' (if they were member functions within that class definition)? I can't do a simple parsing, since for my application the eval strings can become arbitrarily complicated.

Comments
  • That is not "context". You want a property to become a variable. That is a different concept.
  • @trincot rephrased the question
  • @Nayan do you want to check if a is 10? c = (myobj.a == 10)
  • Are your expressions arbitrary JavaScript? If it's some reasonable subset, implementing a way to parse these expressions and execute them would be a better solution than using eval. Also, you should check whether you want to use strict mode or not, as the behavior of eval changes depending on that. I don't see an easy way to use eval to achieve what you want, as it would probably end up depending on the global object and clobbering it. Consider someone wanting to use something from it (say Math.abs()). Your context could have matching properties. What should happen in such case?
  • @Pilan Unfortunately the conditions comes from another source and I can't change them.
  • It should be noted that with statements are forbidden in strict mode code.
  • @JordanRunning, indeed, an important remark. Added.
  • As per your suggestion, I'm trying to parse the conditions and evaluate them. Right now it's easy as there are only some fixed conditions. But parsing and evaluating will become a tough task when the conditions will be complex. In python eval takes a scope object and I expected it in JS too.