Forward declaration in Javascript
Background
I'm 开发者_开发问答building a javascript based application that works differently on mobile and desktop devices. However, except for the DOM manipulation, most code is common between both platforms, so I have structured all files like: * foo.core.js * foo.mobile.js * foo.web.js
And hoping to leverage object oriented techniques to write cleaner code.
Problem:
I have two JavaScript files, with classes
File 1:
function ClassA()
{}
ClassA.prototype.foo = function(){};
GreatGrandChildA.prototype = new GrandChildA(); // this is where the error is
function GreatGrandChildA ()
{}
File 2:
ChildA.prototype = new ClassA();
function ChildA () // ChildA inherits ClassA
{}
GrandChildA.prototype = new ChildA()
function GrandChildA () // GrandChildA inherits ClassA
{}
Normally, in a language like C++, I would forward declare GrandChildA
right in File 1. I would like to know how to do it in Javascript
Edit:
If I make a single file containing all four classes - in the same order in which they are loaded, the example works exactly as expected:
http://jsfiddle.net/k2XKL/
Simple logic for unordered js file loading:
File1:
// ClassB: inherite from ClassA
(function ClassB_Builder() {
if(window.ClassB)return; // ClassB is already defined;
if(!window.ClassA) { // ClassA is already not defined;
setTimeout(ClassB_Builder,0); // shedule class building
return;
}
ClassB=function() {
}
ClassB.prototype=new ClassA;
ClassB.prototype.constructor=ClassB; // can be important for inheritance!!!
})();
File2:
// ClassA: base class
(function ClassA_Builder() {
ClassA=function() {
}
})();
// ClassC: inherite from ClassB
(function ClassC_Builder() {
if(window.ClassC)return; // ClassC is already defined;
if(!window.ClassB) { // ClassB is already not defined;
setTimeout(ClassC_Builder,0); // shedule class building
return;
}
ClassC=function() {
}
ClassC.prototype=new ClassB;
ClassC.prototype.constructor=ClassC; // can be important for inheritance!!!
})();
I assume that on your HTML page, you import File 1 and then File 2.
In File 1, you should see exception because "GrandChildA" is undefined. The function declaration is not done because File 2 has not loaded yet.
In File 2, you're being able to do:
ChildA.prototype = new ClassA();
function ChildA () // ChildA inherits ClassA
{}
because the Javacript runtime hoisted your named function "ClassA" before the code executes until ChildA.prototype = new ClassA();
Please read more about function hoisting and should you be doing it in such situation at http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
The most sane way to accomplish what you want, is to make 2 separate versions of your source code. You're going to want to minify, obfuscate your code and merge all the source files anyway, so it would make sense to create a build script (python would be a great language for a simple build script) that you configure to merge mobile specific files into one (plus the files that both versions share) and non-mobile specific files into another file (and shared files also). In addition you could later add automatic obfuscating and gzipping. Then you can serve the appropriate source version to the appropriate client.
As mentioned in the comments, the requested functionality is not possible. This is not only a technical problem but also an indication that the application is not structured appropritately - the design should be improved. Now, there is a kind of a circular dependency that shoul be avoided.
For comparison you mention that you would solve it in C++ by a forward declaration of the superclass. But this is also not possible. In C++, in order to declare a subclass you need to include the file with the declaration of the superclass. And you cannot solve the problem when there are circular dependencies.
精彩评论