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)
我显然没有包装最高级别,虽然我可以,而程序化版本会.
如果您想接受甚至远程复杂的脚本,这将不起作用。一些潜在的问题:
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)
你大概能明白我的意思。