简体   繁体   English

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

[英]How to execute “eval” without writing “eval” in JavaScript

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

So basically the question is, is there any alternative (maybe creative) way of writing a expression that returns the eval function?所以基本上问题是,是否有任何替代(可能是创造性的)方式来编写返回 eval 函数的表达式? 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谢谢

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当 f 与 A.this 一起应用时,这会发出警报 10

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

But based on Dimitar's answer and some fiddling around, here's what I found.但基于 Dimitar 的回答和一些摆弄,这就是我发现的。 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:似乎 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
  }
});

However, if I store the "top level" local scope (all the code, including mootools, runs inside an anonymous function), then it works:但是,如果我存储“顶级”本地范围(所有代码,包括 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.
  }
});

However this doesn't work in Safari, so bottom line is, what I was trying to do can't be done cross-compatibly.然而,这在 Safari 中不起作用,所以底线是,我试图做的事情不能交叉兼容。 eval is a special touchy function and every browser treats it differently. eval 是一个特殊的敏感函数,每个浏览器都以不同的方式对待它。

是否可以重构对某些不属于被压缩文件的外部填充函数的 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.检查http://www.jsfiddle.net/nGL79/将帧作为不同的评估范围。

and specific to mootools:并且特定于 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希望其中的一些帮助...希望你不会得到函数 eval 必须被直接调用,而不是通过另一个名称的函数

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

If possible you may want to try one of the other compression libraries since YUI isn't the only game in town anymore.如果可能,您可能想尝试其他压缩库之一,因为 YUI 不再是镇上唯一的游戏。

Here is a couple articles on the other compression tools available.这里有几篇关于其他可用压缩工具的文章。

Microsoft and Google seem to do a better job than YUI anyways.无论如何,微软和谷歌似乎比 YUI 做得更好。

This way needs jQuery.这种方式需要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)
        }
    })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM