views:

107

answers:

3

When developing JavaScript, I tend to separate JavaScript code out into different files and then run a script to concatenate the files and compress or pack the resulting file. In the end, I have one file that I need to include on my production site.

This approach has usually worked, but I've started to run into a problems with prototypal inheritance. Specifically, if one class inherits from another class, the file for the parent class needs to be included already for the inheritance to work. If the concatenation script I'm using is simply concatenating a directory full of files, the child class might occur in the code before the parent class. Like this:

*parent_class.js*

var Namespace = Namespace || {};    

Namespace.Parent = function () { };
Namespace.Parent.prototype.doStuff = function () { ... };

*child_class.js*

var NameSpace = Namespace || {};

Namespace.Child = function () { ... };
Namespace.Child.prototype = new Namespace.Parent();

The only way this works is if parent_class.js is included before child_class.js, which might not happen if the concatenation script places the child code before the parent code.

Is there a way to write this code so that the functionality is the same, but the order in which the code is written no longer matters?

Edit: I forgot that I'm using namespaces as well, so I added that to the code as well, which might change things a little bit.

+2  A: 

If the concatenation script I'm using is simply concatenating a directory full of files, the child class might occur in the code before the parent class.

Is it too simple a solution to prepend a sort order value to each filename, and sort by name before performing the operation?

eg:

01_parent.js
02_child.js

Otherwise, perhaps maintaining a preordered list of files in a separate file. Maybe even go one step further and provide a hierarchical dependancy structure in xml to parse? This might be over-engineering the solution a bit :-D

Some options for ways to deal with the problem if you had no way of determining how the javascript files are written.

mercutio
That's actually similar to the approach I'm using right now. Except that I wrote my concatenation script so it looks for a comment at the top of the code that indicates the order to concatenate the script. Files without the order # get put at the end.
Matt Ephraim
Hmm, perhaps that could be adapted to list your "required" scripts for each file in a comment. You could read that, and make the decision to concatenate now, or bubble the current file down the process queue if you haven't seen the required scripts yet.
mercutio
I hadn't thought about that. Interesting idea.
Matt Ephraim
I have been planning on building a similar mechanism myself, but just haven't gotten around to that part of the project I am working on yet. I am sure someone has probably done something like this already, probably just a matter of Googling for it a bit.
Jason Bunting
A: 

I suppose you could do something really hackish like this:

setTimeout(function() { 
  if(typeof(Parent) != "undefined" && typeof(Child) != "undefined") { 
    Child.prototype = new Parent(); 
  } else {
    setTimeout(arguments.callee, 50);
  }
}, 50);

That code could also be anywhere, and would continually run until both the Parent and the Child were loaded...But I wouldn't do that.

Personally, I would just make sure your files are combined in the correct order.

Jason Bunting
The same idea occurred to me too, but you're right, that's pretty hackish.
Matt Ephraim
A: 

If the objects are "namespaced" then you either have to switch to a build solution that incorporates in-order concatenation or use something like dojo.require (but obviously not dojo specific). Basically you want a framework that will provide you with the ability to check if a given identifier is available and pause execution and include it (via evaled ajax or an inserted script tag) if it isn't.

Sasha Sklar