【问题标题】:How to preserve global variables in javascript when using Closure compiler with advanced optimization?使用具有高级优化的 Closure 编译器时如何在 javascript 中保留全局变量?
【发布时间】:2011-05-28 12:29:35
【问题描述】:

我有自己的 Javascript 库,我想通过使用带有高级优化的 Google 闭包编译器来缩小它。通过查看docs,我了解了如何声明在库外使用的函数。

但是我找不到一种方法来保存在我的库中声明的全局变量。闭包编译器只是删除它们,因为它认为它们从未被使用过。有人可以帮忙吗?

编辑:示例代码:

var variable_1 = true;

这是在我的库开始时全局定义的,但它从未在库本身中使用。当它包含在某个页面中时,它在库之外使用。但是那个闭包编译器不知道,这就是它删除这些声明的原因。

【问题讨论】:

  • 你能发布一些示例失败代码吗?

标签: javascript obfuscation google-closure-compiler minify


【解决方案1】:

闭包编译器无法移除声明为window["variable_1"] = true的全局变量

我建议您直接写信给window 以获得全局变量,我还建议您使用字符串文字作为变量名,这样闭包就不会缩小它。

【讨论】:

  • 哦,好的。你能举个例子,你所说的“使用字符串文字作为变量名”是什么意思?
  • @Frodik 他确实举了一个例子 - window["variable_1"] = true
  • @Pointy 我不知道术语“字符串文字”指的是第一段。很抱歉造成误解,现在很清楚了:-) 感谢您的回答和评论
【解决方案2】:

虽然您可以通过将全局变量的所有用法替换为window["varname"] 来引用“真正的”全局变量,但“污染”全局命名空间通常不是一个好主意。闭包编译器旨在阻止您这样做。

CAVEATwindow["varname"]var varname 不一样,因为“窗口”可能并不总是非浏览器环境中的全局对象。事实上,闭包编译器假定全局对象和“窗口”是不同的。例如,window["varname"] 将编译为 window.varname 而不是 var varname。它们相同,尽管在浏览器中它们的工作方式相似。

最好创建一个全局命名空间对象,然后只导出那个对象。你所有的“全局”变量都应该成为这个全局命名空间变量下的属性。好处:

  1. 所有这些全局变量都被重命名为更短的版本
  2. 可能会发生常量内联
  3. 无论如何,闭包编译器都会自动“扁平化”命名空间,因此您的代码不会变慢
  4. 高级混淆
  5. 您的代码也适用于非浏览器环境。请记住,“窗口”可能并不总是存在(例如在服务器端代码中),“全局对象”可能并不总是“窗口”

如果您有用户必须读取/设置才能使用您的库的全局变量,也不鼓励这样做。最好在全局命名空间对象上公开一个 API,然后像往常一样通过 window 对象公开公共 API:window["myLib"]["setConfig"] = myLib.setConfig

在您的情况下,如果您在非闭包编译代码的其他部分使用了全局变量,则必须考虑:

  1. 将这些变量的声明放在由 Closure 编译的文件之外是否更好
  2. 为什么不将这些变量的声明与使用它们的代码放在一起
  3. 您实际上是否应该关闭编译所有代码而不是仅部分代码(有可能吗?您使用其他库吗?)

【讨论】:

    【解决方案3】:

    我刚刚遇到这个问题,我有自己的解决方案。

    在一个自执行函数中创建你的整个库,将所有对象属性作为字符串(每个属性至少一次),如下所示:

    (function () {
        var myLibrary = {
            'myMethod' : function () {
                ...
            }
        }
        myLibrary.myMethod['propertyOfTheMethod'] = '';
    }());
    

    从外部访问它的常用方法是将var myLibrary = 放在函数之前,return myLibrary 放在函数末尾,以便将其分配给全局变量。但是该函数是在全局范围内执行的(因为它是自执行的),所以我们可以使用字符串文字创建this 的属性。完整的:

    (function () {
        var myLibrary = {
            'myMethod' : function () {
                ...
            }
        }
        myLibrary.myMethod['propertyOfTheMethod'] = '';
        this['myLibrary'] = myLibrary;
    }());
    

    但是,这在"use strict"; 下不起作用。在严格模式下获取全局变量的最佳方法是使用var global = Function('return this')();,然后将您的变量分配给它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多