is there any way I can execute eval() on a specific scope (but NOT global)?
for example, the following code doesn\'t work (a is undefined on the sec
Here is a 20-line or so JS class that implements an extensible context using eval in a lexical scope:
// Scope class
// aScope.eval(str) -- eval a string within the scope
// aScope.newNames(name...) - adds vars to the scope
function Scope() {
"use strict";
this.names = [];
this.eval = function(s) {
return eval(s);
};
}
Scope.prototype.newNames = function() {
"use strict";
var names = [].slice.call(arguments);
var newNames = names.filter((x)=> !this.names.includes(x));
if (newNames.length) {
var i, len;
var totalNames = newNames.concat(this.names);
var code = "(function() {\n";
for (i = 0, len = newNames.length; i < len; i++) {
code += 'var ' + newNames[i] + ' = null;\n';
}
code += 'return function(str) {return eval(str)};\n})()';
this.eval = this.eval(code);
this.names = totalNames;
}
}
// LOGGING FOR EXAMPLE RUN
function log(s, eval, expr) {
s = '' + String(s);
if (expr) {
s += ':\n' + expr + ' --> ';
}
s += '';
if (expr) {
try {
s += '' + JSON.stringify(eval(expr)) + '';
} catch (err) {
s += '' + err.message + '';
}
}
document.body.innerHTML += s + '\n\n';
}
document.body.innerHTML = '';
// EXAMPLE RUN
var scope = new Scope();
log("Evaluating a var statement doesn't change the scope but newNames does (should return undefined)", scope.eval, 'var x = 4')
log("X in the scope object should raise 'x not defined' error", scope.eval, 'x');
log("X in the global scope should raise 'x not defined' error", eval, 'x');
log("Adding X and Y to the scope object");
scope.newNames('x', 'y');
log("Assigning x and y", scope.eval, 'x = 3; y = 4');
log("X in the global scope should still raise 'x not defined' error", eval, 'x');
log("X + Y in the scope object should be 7", scope.eval, 'x + y');
log("X + Y in the global scope should raise 'x not defined' error", eval, 'x + y');
.remark {
font-style: italic;
}
.result, .error {
font-weight: bold;
}
.error {
color: red;
}