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:
1. Use Template Literals:
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;
2. Deferred evaluation through callback
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');
}
3. Nested Object Data Structure
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.