-->

Exposing dynamically created functions on objects

2019-05-30 06:18发布

问题:

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.

回答1:

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

  • @export (also see: goog.exportSymbol or goog.exportProperty)
  • Export symbols by storing them on the global object referenced by a string. See Export the Symbols You Want to Keep
  • Define an interface in an externs file and implement the interface (see linked answers below)
  • Quote properties
  • Note: @expose has been deprecated

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:

  • Why does Closure compiler rename properties of an extern type?
  • Can I tell the Closure compiler to, for specific types only, stop renaming properties?
  • John's answer to the question: How to tell Closure Compiler to preserve properties on an object