KingOfHypocrites
KingOfHypocrites

Reputation: 9537

How to force Google Closure Compiler to rename methods even when using objects

It seems that the google closure compiler (http://closure-compiler.appspot.com/home) preserves all of the method names when I use 'this.' or when using a revealing module pattern. It only seems to rename methods to letters when they are not in an object that might be referenced by other external methods. I've tried wrapping both my (Utility) object and the anonymous method that uses it, but this doesn't seem to help. How do you create objects (and separate script files) that might be shared with each other and still have it abbreviate all the method names?

I'm read several posts on SO and do not see anything addressing this, only posts about stuff not getting renamed due to conflicts with external variables.

var Utility = (function () {
    this.isDefined = function (v) {
        /// <summary>Checks to see if a variable is defined.</summary>
        return typeof v !== 'undefined';
    }

this.isObj = function (v) {
    /// <summary>Checks to see if a variable is an object.</summary>
    return typeof v === 'object';
}
...

})();

Then I want to be able to do:

(function(u) {
    u.isDefined(); 
})(Utility);

I've also tried:

 var Utility = (function () {
        var utility = {};

        utility.isDefined = function (v) {
            /// <summary>Checks to see if a variable is defined.</summary>
            return typeof v !== 'undefined';
        }

        utility.isObj = function (v) {
            /// <summary>Checks to see if a variable is an object.</summary>
            return typeof v === 'object';
        }

        return utility;
...

Upvotes: 1

Views: 848

Answers (1)

Chad Killingsworth
Chad Killingsworth

Reputation: 14411

The revealing object pattern does not work well with closure compiler. Nor does the extra closure you are using which aliases the window and document global variables. The final use case itself is problematic with Closure-compiler as well. Currently, the compiler doesn't handle aliases well especially when passing namespaces as function arguments.

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==
var Utility = {};
Utility.isDefined = function (v) {
  /// <summary>Checks to see if a variable is defined.</summary>
  return typeof v !== 'undefined';
};

Utility.isObj = function (v) {
  /// <summary>Checks to see if a variable is an object.</summary>
  return typeof v === 'object';
};

(function() {
   function myPrivateFunction(x) {
   }
   Utility.SomeMethod = function(x) {
     return myPrivateFunction(x);
   };
})();

Utility.isDefined(x);
window['Utility'] = Utility;

Compilation and renaming of this example can be tested at http://closure-compiler.appspot.com/

You can protect your local variables from bleeding into the global scope by using the output_wrapper flag and properly exporting your symbols.

The compiler also specifically disallows usage of the this keyword in non-constructor, non-prototype functions. You should always use the full namespace. The compiler can then flatten the namespace methods (which is why the restriction occurs).

See Which Compilation Level is Right for Me?

Upvotes: 2

Related Questions