Although similar questions have been asked previously, I am interested in current best practices as methodologies evolve rapidly. Just two days ago, Chad Killingsworth commented on an accepted answer from three years ago, stating that the @expose
annotation is now deprecated.
I am currently implementing the module pattern. A working example can be found on this JSFIDDLE link below:
/** @const */
var MATHCALCS = (function () {
'use strict';
var MY = {};
/**
* @constructor
* @param {!Object} obj
* @expose
*/
MY.ModuleStruct = function (obj) {
/** @expose */
this.color = (obj.color !== undefined) ? obj.color : null;
/** @expose */
this.size = (obj.size !== undefined) ? obj.size : null;
};
/**
* @expose
*/
MY.ModuleStruct.prototype.clone = function () {
return new MY.ModuleStruct({
"color": this.color,
"size": this.size
});
};
MY.moduleProperty = 1;
/**
* @type {function(!Array<number>)}
* @expose
*/
MY.moduleMethod = function (a) {
var i, x = 0;
for (i = 0; i < a.length; i += 1) {
x = x + a[i];
}
return x;
};
return MY;
}());
window["MATHCALCS"] = MATHCALCS;
With the usage of @expose
annotation, the code above can be effectively minified using Closure in advanced mode and the subsequent calls are functional (minified example):
// call a public method
alert(MATHCALCS.moduleMethod([1, 2, 3]));
// allocate a new structure
var ms = new MATHCALCS.ModuleStruct({
"color": "red",
"size": "small"
});
alert(ms.color + '\t' + ms.size);
// clone a second instance
var ms2 = ms.clone();
alert(ms2.color + '\t' + ms2.size);
alert(ms !== ms2); // cloned objs are not equal
// and directly update the properties of the object
ms2.color = "white";
ms2.size = "large";
alert(ms2.color + '\t' + ms2.size);
If feasible, I would like to transition the approximately 10,000 lines of code to utilize the @export
annotation without deviating from the module pattern. However, upon replacing @expose
with @export
, Closure throws the following error:
ERROR - @export only applies to symbols/properties defined in the global scope.
Q: Is it achievable, and if so, how should the aforementioned code be annotated for compatibility with ADVANCED_OPTIMIZATIONS?
While I understand I can use notation such as:
MY["ModuleStruct"] = MY.ModuleStruct;
MY["ModuleStruct"]["prototype"]["clone"] = MY.ModuleStruct.prototype.clone;
manually exporting object properties this way may become burdensome. Additionally, JSLint raises concerns about unconventional assignments, therefore utilizing JSDocs annotations seems to be a preferable approach.