Specify scope for eval() in JavaScript?

后端 未结 9 1296
心在旅途
心在旅途 2020-11-27 07:24

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

9条回答
  •  情话喂你
    2020-11-27 07:47

    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;
    }

提交回复
热议问题