Search code examples
google-closure-compilergoogle-closure-library

Exposing dynamically created functions on objects with closure compiler


I am trying to annotate my javascript so that closure doesnt rename all the symbols since i am working with vanilla javascript as well.

/**
* @constructor
* @expose
* @type{foo}
*/

foo = function (el, args) {
"use strict";
var s = "Hello World";
/*
* @expose
* @this {foo}
* @type {function}
*/
this.introduce = function () {
    return s;
 };
};

However the generated output when i run it through the closure compiler with advanced optimization is

foo = function() {
 this.a = function() {
 return"Hello World"

} };

How do i ask closure to preserve the name introduce since this will be called from an external javascript.


Solution

  • The following options may be used to prevent the Closure Compiler from renaming symbols:

    If you do not want to define methods on the function prototype as shown in your example, then you could export the constructor foo with goog.exportSymbol and use @expose to export methods.

    /**
     * @param {Element} el
     * @param {...*} args
     * @constructor
     */
    var foo = function (el, args) {
      "use strict";
    
      /** @private */
      this.msg_ = "Hello World";
    
      /**
       * @this {foo}
       * @return {string}
       * @expose
       */
      this.introduce = function () {
        return this.msg_;
      };
    };
    goog.exportSymbol('foo', foo);
    

    By defining methods on the function prototype, goog.exportSymbol can be used to export both the constructor as well as method names.

    /**
     * @param {Element} el
     * @param {...*} args
     * @constructor
     */
    var foo = function (el, args) {
      "use strict";
    
      /** @private */
      this.msg_ = 'Hello World!';
    };
    goog.exportSymbol('foo', foo);
    
    /**
     * @return {string}
     */
    foo.prototype.introduce = function () {
      return this.msg_;
    };
    goog.exportSymbol('foo.prototype.introduce', foo.prototype.introduce);
    

    See these related stackoverflow questions: