如何在JavaScript中不写“eval”的情况下执行“eval”

时间:2010-02-03 20:50:08

标签: javascript json mootools eval yui-compressor

这是交易, 我们有一个我们想要压缩的大型JS库,但YUI compressor如果找到“eval”语句,则不会完全压缩代码,因为它担心它会破坏其他东西。 这很好,但是我们确切地知道什么是eval'd,所以我们不希望它变得保守,因为在MooTools JSON.decode中有一个eval语句

所以基本上问题是,是否有任何替代(可能是创造性的)方法来编写一个返回eval函数的表达式? 我试了几个,但没有骰子:

window['eval'](stuff);
window['e'+'val'](stuff);
// stuff runs in the global scope, we need local scope

this['eval'](stuff);
// this.eval is not a function

(new Function( "with(this) { return " + '(' + stuff + ')' + "}"))() 
// global scope again

有什么想法吗? THX

7 个答案:

答案 0 :(得分:3)

不确定我是否理解您,但您可以将函数应用于特定的本地(此)范围:

var x = 5;

var f = new Function('alert(this.x)');

function A(x){
    this.x = x;
    f.apply(this,[]);
}

a = new A(10);

这警告10,因为f适用于A.this

答案 1 :(得分:3)

感谢所有的想法,我最终只是在构建脚本中进行文本替换,输出JS,基本上用eval替换$ EVAL $,在所有内容被压缩之后。我希望有一种纯粹的JS方式,但是有这么多不同的eval浏览器实现,最好只留下eval

但根据Dimitar的回答和一些摆弄,这就是我发现的。 似乎这个['eval']不起作用的原因是因为它在MooTools JSON.decode中发生的地方也是一个哈希内部:

var JSON = new Hash({
// snip snip
decode: function(string, secure){
    if ($type(string) != 'string' || !string.length) return null;
    if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;

    return this.eval('(' + string + ')'); // Firefox says: TypeError: this.eval is not a function
}

});

但是,如果我存储“顶级”本地范围(所有代码,包括mootools,在匿名函数内运行),那么它可以工作:

var TOP = this;
var JSON = new Hash({
// snip snip
decode: function(string, secure){
    if ($type(string) != 'string' || !string.length) return null;
    if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;

    return TOP.eval('(' + string + ')'); // All good, things run within the desired scope.
}

});

然而,这在Safari中不起作用,所以底线是,我试图做的不能交叉兼容。 eval是一种特殊的敏感功能,每个浏览器都会以不同的方式对待它。

答案 2 :(得分:1)

是否可以重构对某些外部填充函数的eval调用,该函数不属于正在压缩的文件?

答案 3 :(得分:1)

我错过了什么吗?

var noteval = this.eval; // can be defined before the file is loaded
noteval("alert('not eval. at all');");

(function() {
    console.log(this);
    noteval("alert('chavs!');");
}).bind(window)();

(function() {
    console.log(this);
    noteval("alert('crappy parents');");
}).bind(window.parent)();

将其作为不同的评估范围检查http://www.jsfiddle.net/nGL79/

具体到mootools:

window["ev"+"al"].pass("alert('what');")();
this["ev"+"al"].pass("alert('no!');")(); // local scope too?

var noteval = window["ev"+"al"].create({
    bind: this
}); 

希望其中一些有用...希望你不要得到函数eval必须直接调用,而不是通过其他名称的函数

答案 4 :(得分:0)

var e = "e";
window[e+"val"](stuff);

答案 5 :(得分:0)

如果可能的话,您可能想尝试其他压缩库之一,因为YUI不再是镇上唯一的游戏。

以下是其他压缩工具的几篇文章。

微软和谷歌似乎比YUI做得更好。

答案 6 :(得分:0)

这种方式需要jQuery。

function NotEval(code, callBack) {
    $.ajax({
        url: 'data:application/javascript;charset=utf-8,' + encodeURIComponent(code),
        cache:true,
        success: function (r) {
            if (typeof callBack === "function") {
                callBack()
            }
        },
        error: function (r) {
            console.log("Eval error");
            console.log(r)
        }
    })
}