I have a string containing some conditions, for example:
var str = "this.demoModel.active == '1' && this.demoModel.span > 5 || ..."
Is there a direct way in javascript to parse them so that, they work like a set of conditions. Something like:
if (JSON.parse(str) {})
. ??
In general you should try to avoid getting into this situation at all: storing JavaScript in strings for later evaluation should be avoided if possible. Depending on your actual case you could consider the following option:
They are limited in practical use, since they are parsed together with the script in which they are used, but they are also safe:
var str = `${this.demoModel.active == '1' && this.demoModel.span > 5}`;
When this string is assigned, it will immediately evaluate the ${ }
parts in it.
This is thus only a solution if the evaluation can happen immediately, because you cannot store this in a string and then expect to trigger the evaluation later.
And so it is not much different from:
var bool = this.demoModel.active == '1' && this.demoModel.span > 5;
A work-around could be to define a function that evaluates the template literal or expression, like so:
var rule = function() {
return this.demoModel.active == '1' && this.demoModel.span > 5;
};
... and you can pass that function around, for instance as a callback:
doSomething(rule);
... and then doSomething could call it like this, binding the context, so that this
has the appropriate value:
function doSomething(rule) {
if (rule.call(this)) console.log('rule passed');
}
Another option would be to create an object structure for the expressions, for example like this:
var rules = [
[{ // AND conditions:
"field": "active",
"compare": "eq",
"target": 1
}, {
"field": "span",
"compare": "gt",
"target": 5
}], // Next array will be OR'ed
[{
"field": "...."
"compare": "..",
"target": ...
}]
}];
This is a nested array, where the top level will have rules that must be OR'ed together, while the inner level will be AND'ed together.
Then write a function that will process this structure. The compare names could be mapped to functions in your code, like this:
const comparators = {
"eq": (a, b) = a === b,
"gt": (a, b) = a > b
};
So to evaluate one object in the rules array, you could use this:
execute: (obj) => comparators[this.demoModel[obj.compare]] // get the function
(this.demoModel[obj.field], obj.target) // pass arguments
This rules structure can easily be saved and loaded as JSON string.
There is, but using them is generally a last resort: eval
and the Function
constructor. eval
runs code from a string input, in the context in which eval
is called. The Function
constructor creates a function from a string. Naturally, in both cases, this means you must trust the source of the string, since it can contain any arbitrary code and you're happily running it within the context of your code. So you wouldn't, for instance, take a string from User A and then run it in User B's browser — that would leave User B wide open to attack from User A. (For "browser" substitute "session" or whatever, the problem is just as real — perhaps more so — server-side in an environment like Node as it is client-side in a brwoser.)
If you're accepting the string from a user and running it in their own browser/session/context, that's fine.
Here's an example:
function Foo() {
this.demoModel = {
active: "1",
span: 7
};
}
Foo.prototype.run = function(str) {
if (eval(str)) {
console.log("Yes");
} else {
console.log("No");
}
};
var f = new Foo();
f.run("this.demoModel.active == '1' && this.demoModel.span > 5");
f.run("this.demoModel.active == '0' && this.demoModel.span < 5");
You can also use the Function
constructor, and then call it with the correct this
:
function Foo() {
this.demoModel = {
active: "1",
span: 7
};
}
Foo.prototype.run = function(str) {
var testfunc = new Function("return " + str);
if (testfunc.call(this)) {
console.log("Yes");
} else {
console.log("No");
}
};
var f = new Foo();
f.run("this.demoModel.active == '1' && this.demoModel.span > 5");
f.run("this.demoModel.active == '0' && this.demoModel.span < 5");
If you have to do this, prefer the Function
constructor to eval
where possible, since it doesn't have access to everything in scope where you use it, but they both are powerful tools you need to be wary of.
You can use 'eval' or 'Function' but as stated on MDN
Don't use eval needlessly! - eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.
if(new Function("CONDITON_STRING")()){
//Answer
};
Try the following:
var str = 'true && true';
var str2 = 'true && false';
function strEval(fn) {
return new Function('return ' + fn)();
}
var conditionTrue = strEval(str);
var conditionFalse = strEval(str2)
if(conditionTrue)
{
console.log(conditionTrue)
}
if(!conditionFalse)
{
console.log(conditionFalse)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With