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 mon 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:
/
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 mon 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/k2XKL/
Share Improve this question edited Sep 19, 2011 at 11:38 antileet2 asked Sep 19, 2011 at 11:04 antileet2antileet2 3231 gold badge2 silver badges7 bronze badges 6- Let me get this straight - you want to assign new instance of an class GrandChildA before it has been declared? Javascript natively doesn't support any way to do that. – WTK Commented Sep 19, 2011 at 11:22
- When using plain javascript (without helper libraries) you must download js-file that contains parent class definition before js-file that contains child class definition. For your example: File2 must be downloaded before File1. Or you can merged both files into one. If you need way to download childs classes before parent, you can use external library or implement your custom logic for downloading and creating classes. – Andrew D. Commented Sep 19, 2011 at 11:32
- @WTK: If I put everything in one file, it works great. Unfortunately, the way I've designed it prevents putting everything in one file. but now it looks like I'll have to re-structure the entire application. – antileet2 Commented Sep 19, 2011 at 11:35
- @Andrew - The problem is that the scripts are executing one after the other. So no matter which code executes first, it'll fail. Funnily enough putting both the scripts in the same file solves the issue. But that's something I Cannot do – antileet2 Commented Sep 19, 2011 at 11:37
- @skyronic yes you may need to re-structure your code organization. And read about hoisting in Javascript runtime to understand why your File 2 actually works – Kenny Ki Commented Sep 19, 2011 at 11:45
4 Answers
Reset to default 6Simple 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./2010/2/JavaScript-Scoping-and-Hoisting
The most sane way to acplish 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 ments, 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 parison 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.