如何执行“eval”不写“eval”在 JavaScript 中

发布于 2024-08-20 12:40:42 字数 598 浏览 6 评论 0原文

这是交易, 我们有一个很大的 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

有什么想法吗? 谢谢

Here's the deal,
we have a big JS library that we want to compress, but YUI compressor doesn't fully compress the code if it finds an "eval" statement, out of fear that it will break something else.
That's great and all, but we know exactly what is getting eval'd, so we don't want it to get conservative because there's an eval statement in MooTools JSON.decode

So basically the question is, is there any alternative (maybe creative) way of writing a expression that returns the eval function?
I tried a few, but no dice:

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

Any ideas?
Thx

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

随梦而飞# 2024-08-27 12:40:42

感谢所有的想法,我最终只是在输出 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 是一个特殊的敏感函数,每个浏览器都会以不同的方式对待它。

Thanks for all the ideas, I ended up just doing text replacement in the build script that outputs the JS, basically replacing $EVAL$ with eval, after everything has been compressed. I was hoping for a purely JS way, but with so many different eval browser implementations, it's probably better to just leave eval alone

But based on Dimitar's answer and some fiddling around, here's what I found.
Seems like the reason why this['eval'] wasn't work is because the place where it's happening, in MooTools JSON.decode, is also a inside a Hash:

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

However, if I store the "top level" local scope (all the code, including mootools, runs inside an anonymous function), then it works:

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

However this doesn't work in Safari, so bottom line is, what I was trying to do can't be done cross-compatibly. eval is a special touchy function and every browser treats it differently.

感悟人生的甜 2024-08-27 12:40:42

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

var x = 5;

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

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

a = new A(10);

当 f 与 A.this 一起应用时,此警报 10

Not sure if I understood you, but you can apply a function to a specific local (this) scope:

var x = 5;

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

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

a = new A(10);

This alerts 10 as f is applied with A.this

用心笑 2024-08-27 12:40:42

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

Could refactor eval calls to some external shim function that is not part of the file being compressed?

π浅易 2024-08-27 12:40:42

我错过了什么吗?

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 必须直接调用,而不是通过另一个名称的函数

am i missing something?

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)();

check it http://www.jsfiddle.net/nGL79/ with the frames as different eval scopes.

and specific to mootools:

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

and

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

hope some of that helps... hope you don't get function eval must be called directly, and not by way of a function of another name though

心安伴我暖 2024-08-27 12:40:42
var e = "e";
window[e+"val"](stuff);
var e = "e";
window[e+"val"](stuff);
懵少女 2024-08-27 12:40:42

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

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

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

If possible you may want to try one of the other compression libraries since YUI isn't the only game in town anymore.

Here is a couple articles on the other compression tools available.

Microsoft and Google seem to do a better job than YUI anyways.

浮云落日 2024-08-27 12:40:42

这种方式需要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)
        }
    })
}

This way needs 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)
        }
    })
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文