5

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

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

编辑:示例代码:

var variable_1 = true;

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

4

3 回答 3

7

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

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

于 2011-05-28T13:26:25.187 回答
3

尽管您可以通过用 替换该全局变量的所有用法来引用“真正的”全局变量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. 你真的应该关闭编译所有代码而不是只编译一部分(有可能吗?你使用另一个库吗?)
于 2011-05-29T05:38:45.023 回答
1

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

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

(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')();然后将您的变量分配给它。

于 2012-01-03T10:17:02.647 回答