递归使用eval()是一种检查程序执行的好方法吗?

teh*_*ter 5 javascript interpreter metaprogramming

在过去的几天里,我一直在构建一个基本的实时评估javascript开发环境(我称之为WEPL.),并意识到能够将错误消息与行号相关联是件好事.不幸的是,eval()并没有提供一个很好的方法,我可以找到.

到目前为止我提出的解决方案是在eval()之前转换源,这样它就是一组嵌套调用eval()的包装器,它在eval之前记录一些信息,检查eval是否成功,以及然后使用该信息向用户输出更有用的故障排除信息.

我的问题是,为什么这可能是一个坏主意?我需要解决哪些问题才能确保效果良好?

我的意思是一种转变的例子,只是为了使这个具体化.

这个

if (cond) {
  return foo + bar;
}
else {
  return baz + quux;
}
Run Code Online (Sandbox Code Playgroud)

变成了这个

if (myEval('cond')) {
  return myEval("myEval(\"foo\") + myEval(\"bar\")");
else {
  return myEval("myEval(\"baz\") + myEval(\"quux\")");
}
Run Code Online (Sandbox Code Playgroud)

我显然没有包装最高级别,虽然我可以,而程序化版本会.

Tgr*_*Tgr 3

如果您想接受甚至远程复杂的脚本,这将不起作用。一些潜在的问题:

范围

var i = 1; // global scope
!function() {
    var i = 2; // function scope
}();
alert(i); // 1
Run Code Online (Sandbox Code Playgroud)

myEval('var i = 1;'); // global scope
myEval('!function() {
    myEval(\'var i = 2;\'); // eval has global scope, always
}();');
myEval('alert(i);'); // 2
Run Code Online (Sandbox Code Playgroud)

闭包

!function() {
    var i = 1; // local to outer function
    !function() { // inherits context from outer function
        alert(i); // 1
    }();
}();
Run Code Online (Sandbox Code Playgroud)

myEval('!function() {
    myEval(\'var i = 1;\'); // local to outer function
    myEval(\'!function() { // eval has global scope; myEval inherits from wherever it was defined
        myEval(\\\'alert(i);\\\'); // undefined
    }();\');
}();');
Run Code Online (Sandbox Code Playgroud)

var obj = {
    n: 1,
    f: function() {
        return this.n; // this is the object f is called from
    }
}
alert(obj.f()); // 1
Run Code Online (Sandbox Code Playgroud)

myEval('var obj = {
    n: myEval(\'1\'),
    f: myEval(\'function() {
           return myEval(\\\'this.n\\\'); // this is always the window in eval
       }')
}');
myEval('alert(obj.f());'); // undefined
Run Code Online (Sandbox Code Playgroud)

逃脱蠕变

您需要转义每个引号,也需要转义转义符号。在包含大量对象、闭包、内部函数等的代码中,这将导致转义标志变得难以管理:

!function() {
    $(function() {
        $('#foo').click(function() {
            setTimeout(function() {
                $.post('/', function(res) {
                     log(res);
                });
            }, 1000);
        });
    });
}();
Run Code Online (Sandbox Code Playgroud)

(请注意,这不是一个特别设计或复杂的示例,它只涉及在某个事件上触发回调的延迟操作)

myEval('!function() {
    myEval(\'$(myEval(\\\'function() {
        myEval(\\\\\\\'$(\\\\\\\'#foo\\\\\\\').click(myEval(\\\\\\\\\\\\\\\'function() {
            myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'setTimeout(myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'function() {
                myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'$.post('/', myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'function(res) {
                     myEval(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'log(res);\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
                }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'));\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
            }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'), 1000);\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
        }\\\\\\\\\\\\\\\'));\\\\\\\');
    }\\\'));\');
}();');
Run Code Online (Sandbox Code Playgroud)

你大概能明白我的意思。