简体   繁体   中英

How to preserve global variables in javascript when using Closure compiler with advanced optimization?

I have my own Javascript library, which I want to minify by using Google closure compiler with Advanced optimization. By looking at the docs I see how to declare functions which are used outside of the library.

However I couldn't find a way how to preserve global variables declared in my library. Closure compiler just removes them, because it thinks they are never used. Anybody can help?

Edit: example code:

var variable_1 = true;

This is defined globally right at the beginning of my library, but it's never used in the library itself. It is used outside the library when it is included in some page. But that Closure compiler doesn't know and thats the reason it removes these declarations.

The closure compiler cannot remove global variables declared as window["variable_1"] = true

I recommend you write to window directly for global variables and I also recommend you use string literals for your variable names so that closure doesn't minify it.

Although you can refer to a "true" global variable through replacing all usage of that global variable with window["varname"] , it is usually not a good idea to "pollute" the global namespace. The Closure Compiler is designed to discourage you from doing this.

CAVEAT : window["varname"] and var varname are not the same, as "window" may not always be the global object in non-browser environments. As a matter of fact, the Closure Compiler assumes that the global object and "window" are different. For example, window["varname"] will compile to window.varname instead of var varname . They are NOT the same, although in a browser they work similarly.

It is best to make a global namespace object, then only export that one object. All your "global" variables should become properties under this global namespace variable. Benefits:

  1. All those global variables are renamed to shorter versions
  2. Inlining of constants can happen
  3. The Closure Compiler automatically "flattens" the namespace anyway, so your code won't be any slower
  4. Superior obfuscation
  5. Your code also works in non-browser environments. Remember, "window" may not always exists (eg in server-side code) and the "global object" may not always be "window"

If you have global variables that the user must read/set to use your library, it is also discouraged. It is better to expose an API on the global namespace object, then expose the public API's as usual through the window object: window["myLib"]["setConfig"] = myLib.setConfig .

In your case, if you have global variables used in other parts of your non-Closure-Compiled code, you have to consider:

  1. Is it better to put the declaration of those variables outside of the file being compiled by Closure
  2. Why are you not putting the declaration of those variables together with the code using them
  3. Should you actually be Closure-compiling all the code instead of only a portion (it is possible? Do you use another library?)

I've just come across this, and I have my own solution.

Create you're entire library within a self-executing function, putting all the object properties as strings (at least once for each property) like so:

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

The usual way to make this accessible from the outside would be to put var myLibrary = before the function and return myLibrary at the end of it so that it gets assigned to a global variable. But the function is executed in the global scope (because it's self-executing), so we can create a property of this using a string literal. So in full:

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

But, this won't work under "use strict"; . The best way to get the global variable in strict mode is with var global = Function('return this')(); then assign your variable to that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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