【问题标题】:Closure compiler selective optimization?关闭编译器选择性优化?
【发布时间】:2014-07-09 05:23:53
【问题描述】:

我正在使用 Google 的闭包编译器优化(简单优化)来减小我的一些 JS 脚本文件的大小。虽然这很好用,但我在一些函数中遇到了 eval 语句的问题,编译器替换局部变量会造成严重破坏。我可以尝试重新编码有问题的函数来击败编译器,但这可能会很痛苦——而且从长远来看是危险的,因为我今天使用的技巧可能明天就行不通了。

如果我可以简单地标记我希望编译器保持不变的代码位会更好。目前,我正在考虑采用所有使用 eval 的函数,将它们放在一个单独的文件中,并在编译器输出的末尾标记该文件。但是,在我这样做之前,我认为值得在这里问一下——有没有办法告诉编译器跳过某些函数的优化。例如

//  @compilation_level SIMPLE_OPTIMIZATIONS
function test(one,two)
{

}

function testTwo(alpha,beta)
{

}

// @Closure:Skip

function evalFunc(one,two)
{
 //eval code here
}

//@Closure:EndSkip

最终结果 - Skip、EndSkip 部分之间的代码无需任何更改即可通过编译器。

我查看了文档,但没有找到任何可能做到这一点的东西。

【问题讨论】:

标签: javascript google-closure-compiler


【解决方案1】:

documentation 中有一些关于这个问题的提示。由于编译 eval 通常会失败,建议的跳过功能在大多数情况下可能无法解决任何问题。

如果您没有访问evalFunc 范围之外的任何变量,您可以尝试使用括号表示法将所有局部变量重构为属性并将所有属性名称放在引号中,以便它们won't be renamed

例如,

function evalFunc(one) {
    this['foo'] = one;
    eval('alert(foo);');
}
evalFunc.call({}, 1);

大概会编译成

function(a) {
    this.foo = a; 
    eval("alert(foo);");
};
a.call({}, 1);

保持评估工作。它适用于简单模式和高级模式。

【讨论】:

  • 编译器应该抱怨您的示例中危险地使用了 this 关键字。最好使用window 或明确对象。
  • 这个解决方案似乎是一个非常糟糕的主意。您基本上是将所有值放入全局范围并可能覆盖全局值。
  • 你说得对,我已经添加了一些明确的函数上下文。
【解决方案2】:

谢谢你,@kapep。正如我经常想的那样(当我没有大声想出来的时候),这是一个多么棒的小论坛啊!为了其他寻求做类似事情的人的利益 - 我需要处理的最初问题是

function evalFunc(leNom)
{
 var str,obj = {'age':18};
 obj.name = leNom;
 str = 'var out = obj.name + " is " + obj.age + " years old"';
 eval(str);
 alert(out);
}

通过 Closure 的简单优化运行它,你会得到

  function evalFunc(a){eval('var out = obj.name + " is " + obj.age + " years old"');
  alert(out)};

它倒在脸上。

改成

function evalFunc(leNom)
{
 var str;
 this['obj'] = {'age':18};
 this['obj'].name = leNom;
 str = 'var out = obj.name + " is " + obj.age + " years old"';
 eval(str);
 alert(out);
}

闭包又回来了

function evalFunc(a){this.obj={age:18};this.obj.name=a;
eval('var out = obj.name + " is " + 
obj.age + " years old"');alert(out)};

效果很好!

*----------------- 经过一些测试后的脚注。如果像我一样,您无法避免 JS 中的 eval 并且想要压缩或以其他方式混淆您的代码,请注意前面的道路充满了陷阱。一个粗心的编辑就是破坏你的代码所需要的。 Microsoft 的 AJAX minifier 提供了对包含 eval 的代码的更多控制,因此它可能是一个更好的解决方案。然而,到目前为止,最安全的做法是简单地将所有包含 evals 的函数取出,将它们放在一个单独的文件中,并将其标记到压缩输出中。在任何编写良好的代码中,带有 eval 的函数应该相对不常见。这与 gzip 压缩一起确保了良好的带宽使用,同时避免了流氓 eval 在压缩后出错的噩梦。

【讨论】:

  • 看到编译器根本不接触字符串,也许您可​​以通过从字符串创建整个函数来利用这一点。
【解决方案3】:

如果代码不太复杂,可以使用函数构造函数:

new Function("a", "b" "return eval('a + b')");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多