Organizing and Documenting Multi-File JavaScript Projects - javascript

I'm beginning a fairly large JavaScript project. The project will have everything exist within one or more namespaces, so only a sparse number of things will exist in the global scope (at the moment, there is only one thing).
In order to keep things organized, I would like to keep each class in its own file (much like you would other many other languages) instead of in "modules".
I built a little compilation script (with NodeJS) which will compile all of the files in to a single JavaScript file at the end of the day.
I thought I had a good method, but I'm trying to get JSDoc(3) to cooperate with me and not having a lot of luck, so I'm wondering if I'm maybe tackling this in the wrong way, or if there is some trick with JSDoc I'm missing.
In the source, each namespace is a folder and each class is a file of the same name.
Each class file looks something like this:
var BaseNS = BaseNS || {};
BaseNS.SubNS = BaseNS.SubNS || {};
BaseNS.SubNS.MyClass = (function() {
function MyClass() {
}
Object.defineProperties(MyClass.prototype, {
'someProp', {
getter: function() { return this._someProp = this._someProp || 0; },
setter: function(val) { this._someProp = val; }
}
// ... more
});
MyClass.prototype.someMethod = function() {};
// ... more
return MyClass;
}}());
When compiled together, my compilation script handles dependencies to get the classes in the correct order and also removed duplicate namespace declaration lines.
I think this method is relatively clean and straight-forward. The catch is, I can't figure out how to write the JSDoc documentation in a way which gives me things as I think they should be.
I would like to go with a "class-like" method for things. This is actually for an application which is largely removed from the DOM. Also, I'd like the entire project to be vanilla, modern JavaScript (i.e., no RequireJS, etc.)
Any ideas how to get this documented, or a better way to arrange things?
Thanks.

After playing around with various things for about four hours yesterday, I think I've figured out the optimal format, which combines nice efficent form while allowing for minimal comments to get things to parse properly.
"use strict";
/** #namespace */
var NS = NS || {};
/** #namespace */
NS.Sub = NS.Sub || {};
/**
* #class
*/
NS.Sub.SomeClass = (function(NS) {
/**
* #constructor
* #lends NS.Sub.SomeClass
*/
var SomeClass = function() {
/** #method */
this.someFunc = function(cookie) {
};
Object.defineProperties(this, /** #lends NS.Sub.SomeClass */ {
/**
* #type {number}
* #instance
*/
somePublicProp: {
getter: function() { return this._somePublicProp || 24; },
setter: function(val) { this._somePublicProp = val; }
}
});
};
return SomeClass;
})(NS);
If anyone has any recommendations on how to make this better, I'd love to hear them. In particular, I can't figure out a way to get rid of the need for var SomeClass; ... return SomeClass. I'd like to just return it directly (preferably without any name), but then JSDoc loses track of my method, which means more comments, which isn't cool.

Related

How to document function methods and prototypes from within IIFE using JSDoc

I have struggled to try and figure out a good way of doing this, but to no avail. Maybe someone here can help me document an IIFE like the following
var module = (function(){
var main = function() {
return Object.create(main.prototype);
};
main.foo = function() {};
main.prototype.foo = function() {};
return main;
}());
Module can then be used like jQuery where you can call module(), module.foo() or module().foo() and I need to document all of those calls clearly.
Edit: Specifically, what JSDoc annotations can I use to document the public API of this module? I've tried mixtures of #namespace, #module, #alias and #memberof and either the prototype functions do not show, or they do, but they are indistinguishable from the primary functions.

Google closure library goog.forwardDeclare namespace javascript

I have some problem, and I sure community can help me )))
For Example: I have the next javascript files
file1.js
goog.provide('namespace.ModuleName');
goog.require('namespace.ModuleName.Item')
/**
* #param {Object} args
*#constructor
*/
namespace.ModuleName = function(args) {
....
..Initialization..
...
var item = [];
item.push(new namespace.ModuleName.Item(args)) // THIS ERROR
}
/**
* #private
*/
namespace.ModuleName.prototype.MyMethod = function() {
...
...
...
}
The next part. I want create new file
file2.js
goog.provide('namespace.ModuleName.Item')
/**
* #param {Object} args
*#constructor
*/
namespace.ModuleName.Item = function(args) {
}
I have some problem because "namespace.ModuleName.Item" Doesn't know about namespace.ModuleName. I can fix it. I need write goog.require('namespace.ModuleName') below goog.provide('namespace.ModuleName.Item').
But I have again some problem. Google Closure compiler writes "Require LOOP" . I can delete line where "goog.require('namespace.ModuleName.Item')". But these solution is not correct
What's the correct way to name modules
I ask this question on google forum. Guys told me "use goog.forwardDeclare"
https://groups.google.com/forum/#!topic/closure-library-discuss/PptH2fzcs_M
I tried write goog.forwardDeclare('namespace.ModuleName') above\below goog.provide('namespace.ModuleName.Item'). But it it's not worked for me. Can you help me ? Please. Or maybe write some examples. How use goog.forwardDeclare.

typedef of this variable doesn't produce warning

I want to produce a warning for a number if a string is assigned to it. So, I thought typedef of Closure might do this for me. I tried the following -
var Widget = function()
{
/** #typedef {number} */
this.size = null;
};
new Widget().size = "kaboom!"
When I compile it using http://closure-compiler.appspot.com/home it doesn't throw a warning or error. What am I doing wrong? And/or what other tool should I be using?
Turn the optimization up to Advanced in the closure compiler service to catch these warnings. You still won't see any for your example (well, you will see some, but not what you are expecting), because typedefs are used to define custom types. Also, you need to annotate your constructor. Run the following example in advanced mode and you will see your warnings. Instead of making a typedef for a simple thing like number, I would just use #type, but this example is to show you the proper use of typedef.
/** #typedef {number} */
var customType;
/** #constructor */
var Widget = function()
{
/** #type {customType} */
this.size = null;
};
new Widget().size = "kaboom!"

Javascript Module Pattern and Google Closure Compiler

I am using the Google Closure Compiler on a Drupal project right now. My Javascript is structured using the Javascript Module Pattern.
Because of the way Drupal works, I am compiling each JS file individually. Simple Compilation mode works well, but I would like to use Advanced Compilation on each file.
My files are all variations on
var FOO = (function(me, $, Drupal, undefined) {
function init (context, settings) {
do_sutff();
};
Drupal.behaviors['FOO'] = {
attach: init
};
return me;
}(FOO || {}, jQuery, Drupal));
My problem is that Drupal.behaviors is a specific object in Drupal, and the attach property also is a specific property. When a Drupal page renders, Drupal.behaviors gets looped through, and all of the attach functions are called with the proper arguments. In other words, I don't want anything renamed with the Drupal object.
When I use Advanced Compilation mode, I get
var c = function(a, d, b) {
b.b.FOO = {a:function() {
do_stuff()
}};
return a
}(c || {}, jQuery, Drupal);
I have tried many variations on trying to get the compiler to recognize the whole Drupal object as an extern without luck. No matter what I try, .behaviors and .attach always get renamed.
Is there a way to tell the compiler to keep its hands off an entire object?
There is no concept "Don't modify any properties on this object". You can however setup an extern such as:
/** #interface */
function DrupalBehavior() {}
DrupalBehavior.prototype.attach = function(){};
/** #constructor */
function DrupalObject () {}
/** #type {Object.<string, DrupalBehavior>} */
DrupalObject.prototype.behaviors = {};
Then, in your code:
var FOO = (
/**
* #param {Object} me
* #param {jQuery} $
* #param {DrupalObject} Drupal
* #param {*=} undefined
*/
function(me, $, Drupal, undefined) {
function init (context, settings) {
do_sutff();
};
Drupal.behaviors['FOO'] = {
attach: init
};
return me;
}(FOO || {}, jQuery, Drupal));
In this case the Drupal argument will be renamed, but the behaviors property and its associated attach sub-property will not be.
One note on jQuery: You are passing the jQuery namespace object into the function as a
parameter. Closure-compiler does not trace the type well in this object. The annotation I have listed would be for an instace of the jQuery object as opposed to the entire jQuery namespace. This is probably not what you intended. The only type-safe way to handle this in Closure-compiler is NOT to pass namespaces through function closure.
Update: After looking through the JavaScript Module Pattern post you linked, they encourage passing global namespace objects into function closures. This pattern has known problems with Closure-compiler. You will need to choose to either follow the pattern in this regard or opt for full compatibility with ADVANCED_OPTIMIZATIONS.

Is this parasitic inheritence pattern any good?

Prototypal object creation in JavaScript is claimed to be powerful (I hear it is efficient and if used correctly very expressive). But for some reason I find that it trips me up much more often than it helps me.
The main problem I have with patterns for object creation involving prototype is that there is no way to bypass the need for this. The main reason is that objects that are anything beyond very primitive, for example objects that populate themselves through asynchronous API calls, this breaks down due to change of scope.
So, I use prototypal object creation for objects that I know everything about from the beginning.
But for objects that need to do for example API calls to keep themselves up to date I completely skip prototype and use straight up object literals.
When I feel the need for extending one of these objects, I have used parasitic inheritence:
var ROOT = ROOT || {};
ROOT.Parent = function () {
var self = {
func1 : function () {
alert("func1")
};
}
return self;
};
ROOT.Child = function () {
var self = ROOT.Parent(); // This is the parasitizing
self.func2 = function () {
alert("func2")
};
return self;
};
var myChild = ROOT.Child();
myChild.func1(); // alerts "func1"
myChild.func2(); // alerts "func2"
Using this pattern, I can reuse the code for func1 in the ROOT.Child object. However if I want to extend the code in func1 I have a problem. I.e if I want to call the code in the parents func1 and also my own func1 this pattern presents a challenge. I cannot do this:
ROOT.Child = function () {
var self = ROOT.Parent();
self.func1 = function () {
alert("func2")
};
};
Since this will completely replace the function. To solve this I have come up with the following solution (which you can also check out here: http://jsfiddle.net/pellepim/mAGUg/9/).
var ROOT = {};
/**
* This is the base function for Parasitic Inheritence
*/
ROOT.Inheritable = function () {
var self = {
/**
* takes the name of a function that should exist on "self", and
* rewires it so that it executes both the original function, and the method
* supplied as second parameter.
*/
extend : function (functionName, func) {
if (self.hasOwnProperty(functionName)) {
var superFunction = self[functionName];
self[functionName] = function () {
superFunction();
func();
};
}
},
/**
* Takes the name of a function and reassigns it to the function supplied
* as second parameter.
*/
replace : function (methodName, func) {
self[methodName] = func;
}
};
return self;
};
/**
* "Inherits" from ROOT.Inheritable
*/
ROOT.Action = function () {
var self = ROOT.Inheritable();
/**
* I intend to extend this method in an inheriting object
*/
self.methodToExtend = function () {
alert("I should be seen first, since I get extended");
};
/**
* I intend to replace this method in an inheriting object
*/
self.methodToReplace = function () {
alert("I should never be seen, since I get replaced.");
};
return self;
};
/**
* "Inherits" from ROOT.Action.
*/
ROOT.Task = function () {
var self = ROOT.Action();
self.extend('methodToExtend', function () {
alert("I successfully ran the extended code too.");
});
/**
* I know it is completely unecessary to have a replace method,
* I could just as easily just type self.methodToReplace = function () ...
* but I like that you see that you are actually replacing something.
*/
self.replace('methodToReplace', function () {
alert("I successfully replaced the \"super\" method.");
});
return self;
};
var task = ROOT.Task();
task.methodToExtend(); // I expect both the "base" and "child" method to run.
task.methodToReplace(); // I expect only the "child" method to run.
Ok, so I should ask a question. Am I completely off target here or am I on to something? What are the apparent drawbacks?
No, you're not off target. But you did not invent that wheel also. That type of ECMAscript inheritance became very famous with Doug Crockfords book Javascript: The good parts.
It is a nice pattern and uses closures nicely to keep things private and protected. However, it's still up to you which patterns you prefer (plain prototypal inheritance, pseudo-classical).
With ES5 and new possiblitys like Object.create() and Object.defineProperties(), Object.freeze() to name a few, we also have good ways to have protection and privacy with a more prototypal approach. Personally, I still prefer and like the pseudo classical way, using closures to do stuff.
The caveat still might be function-calls overhead which you generally can avoid using a plain prototypal inheritance. We need to make a whole lot more calls to get things properly done (if things grows). Still, closures are considered to be a little memory greedy and probably be a reason for leaks if we use them sloppy or forget to clean up references here and there. I don't have any reference for this now, but I strongly believe that the latest js engines are not much slower using closures like a lot.

Categories