8

事情是这样的,我们有一个大的 JS 库要压缩,但是如果YUI 压缩器找到“eval”语句,它不会完全压缩代码,因为担心它会破坏其他东西。这很好,但我们确切地知道评估了什么,所以我们不希望它变得保守,因为 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

有任何想法吗?谢谢

4

7 回答 7

4

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

但是根据 Dimitar 的回答和一些摆弄,这就是我发现的。似乎 this['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 是一个特殊的敏感函数,每个浏览器都以不同的方式对待它。

于 2010-02-03T23:57:08.057 回答
3

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

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 一起应用

于 2010-02-03T22:59:52.963 回答
1

是否可以重构对某些不属于被压缩文件的外部 shim 函数的 eval 调用?

于 2010-02-03T22:45:09.123 回答
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)();

检查它ht​​tp ://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 必须直接调用,而不是通过另一个名称的函数

于 2010-02-03T23:14:16.257 回答
0
var e = "e";
window[e+"val"](stuff);
于 2010-02-03T20:52:41.807 回答
0

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

这里有几篇关于其他可用压缩工具的文章。

无论如何,微软和谷歌似乎比 YUI 做得更好。

于 2010-02-03T20:53:12.167 回答
-1

这种方式需要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)
        }
    })
}
于 2017-05-05T02:17:23.513 回答