Eval
is generally avoided as it allows the client to insert and evaluate their own expressions in your code.
That being said, JavaScript being a client side language already allows full access to the user, so there isn't really a good reason not to use it.
As long as the user can only mess with their own session, i wouldn't worry. Security should be handled server side anyway so: Beware but don't simply ignore Eval
.
EDIT 1 - Defending Eval
The comments pointed out some issues, mainly Performance/Optimization impact, which this answer explains in depth. Basically, since it's Just-In-Time compiling anyway, you don't really lose that much in terms of performance.
As for an example on a use case, here is a template example i whipped up, which also uses the controversial with
statement:
var Template = /** @class */ (function () {
function Template(html) {
this.html = html;
}
Template.prototype.apply = function (params, returnDOMObject) {
if (params === void 0) { params = {}; }
if (returnDOMObject === void 0) { returnDOMObject = false; }
with (params) {
var html = eval('`' + this.html.replace(Template.regexes.encapsulated, function (n) {
return n
.replace(Template.regexes.start, '${')
.replace(Template.regexes.end, '}');
}) + '`');
}
if (returnDOMObject) {
return document.createRange().createContextualFragment(html);
}
return html;
};
Template.regexes = {
encapsulated: new RegExp('{{.*?}}', 'igm'),
start: new RegExp('\{{2,}', 'igm'),
end: new RegExp('\}{2,}', 'igm')
};
return Template;
}());
//TEST
var persons = [
{ name: "Peter", age: 25 },
{ name: "Ole", age: 55 },
];
var templates = [];
var container = document.body.appendChild(document.createElement("div"));
var leftBox = container.appendChild(document.createElement("div"));
var rightBox = container.appendChild(document.createElement("div"));
leftBox.style.width = rightBox.style.width = "50%";
leftBox.style.height = rightBox.style.height = "500px";
leftBox.style.cssFloat = rightBox.style.cssFloat = "left";
var leftList = leftBox.appendChild(document.createElement("select"));
leftBox.appendChild(document.createElement("br"));
var leftText = leftBox.appendChild(document.createElement("textarea"));
leftText.style.width = "100%";
leftText.style.resize = "vertical";
var rightOutput = rightBox.appendChild(document.createElement("div"));
function updateLists() {
leftList.innerHTML = '';
for (var i = 0; i < templates.length; i++) {
var template = templates[i];
var option = document.createElement("option");
option.value = option.innerHTML = template.name;
leftList.appendChild(option);
}
}
var h1Template = new Template("<h1>{{name}}</h1>");
var h2Template = new Template("<h2>{{age}} is no age!</h2>");
var pTemplate = new Template("<p>{{name}} may be {{age}}, but is still going strong!</p>\n<p>(When he's {{age*2}} though...)</p>");
var personTemplate = new Template("<p>\n{{ h1Template.apply(params) }}\n{{ h2Template.apply(params) }}\n{{ pTemplate.apply(params) }}\n</p>");
templates.push({ name: "personTemplate", template: personTemplate });
templates.push({ name: "h1Template", template: h1Template });
templates.push({ name: "h2Template", template: h2Template });
templates.push({ name: "pTemplate", template: pTemplate });
function updateOutput() {
rightOutput.innerHTML = '';
for (var pi = 0; pi < persons.length; pi++) {
var person = persons[pi];
rightOutput.appendChild(personTemplate.apply(person, true));
}
}
function leftTextChange() {
templates.find(function (val) { return val.name === leftList.value; }).template.html = leftText.value;
updateOutput();
}
function leftListChange() {
leftText.value = templates.find(function (val) { return val.name === leftList.value; }).template.html;
}
updateLists();
leftList.onchange = leftList.onkeyup = leftListChange;
leftText.onchange = leftText.onkeyup = leftTextChange;
leftListChange();
updateOutput();
Here the users input text is being interpreted live, while the user is watching. No security concerns, since it's all client side.