2010-02-03 138 views
7

以下是我们想要压缩的大型JS库,YUI compressor如果发现“eval”语句没有完全压缩代码,因为担心它会破坏别的东西。 这是伟大的,所有的,但我们确切地知道什么是越来越eval'd,所以我们并不想让它变得保守,因为有在MooTools的JSON.decode的eval语句如何在不写“eval”的情况下执行“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

+0

因为'eval'不被认为是一种普通的功能,你可能会胜过YUI压缩器,但是你会遇到浏览器,它们不会或很快不会让你用任何其他名称调用'eval'。 – 2010-02-03 23:29:35

回答

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是一种特殊的敏感功能,每个浏览器都以不同的方式对待它。

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

这不起作用,事情在全球范围内运行。也似乎不是可移植的,webkit问题'window [“e”+“val”](stuff)''' – adamJLev 2010-02-03 20:55:31

+0

'? – elcuco 2010-02-03 20:56:54

+0

'window.eval ===窗口['eval'] ===窗口['e'+'val']'所以没有骰子..东西得到eval'd在窗口范围这不是我们所需要的 – adamJLev 2010-02-03 21:01:56

0

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

下面是关于其他可用压缩工具的一些文章。

微软和谷歌似乎也是闲着比YUI做得更好。

+0

谢谢为建议。 我已经玩过Google Closure,但它对我们来说过于激进,重命名了太多东西并打破了代码。需要一些时间来调整代码才能运行,并且可能会引入新的错误。 这将是很好的检查MS的东西,但我们是一个Java/OSX店 – adamJLev 2010-02-03 20:59:47

+0

谷歌关闭的窍门是只使用简单压缩,如果失败只是使用空白。这是一个安全的选择,只是删除所有的空白,这比没有好。 – 2010-02-03 21:31:23

+0

这也适用于YUI,它缩小了所有这一切,但它并没有用较短的变量替换长变量名称,因为这些变化 – adamJLev 2010-02-03 22:31:08

1

可以重构eval调用一些外部填充函数,它不是被压缩文件的一部分吗?

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

是我遗漏了什么?

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/与帧作为不同的eval范围。

而具体到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必须直接调用,而不是由路另一个名字的功能虽然

+0

感谢这些想法,至少现在我明白为什么this.eval不起作用了。看看我自己的答案 – adamJLev 2010-02-04 00:00:16

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) 
     } 
    }) 
} 
相关问题