methods of parent class undefined in subclass in javascript
function FML_Field(id){
this.id= id;
this.optional= true;
this.node= null;
if(this.id === undefined){
throw ""; //should provide Id;
}
var this.node= document.getElementById(this.id);
if(this.node === null){
throw "";
}
this.setAsOptional= function(){
this.optional= true;
};
this.setAsRequired= function(){
this.optional= false;
};
this.isOptional= function(){
return this.optional;
};
}
and its son:
function FML_Text(id){
this.prototype= new FML_Field(id);
FML_Text.prototype.constructor= FML_Text;
this.maxLength= false;
this.minLength= false;
this.setMaxLength= function(maxLength){
this.maxLength= maxLength;
}
this.getMaxLength= function(){
return this.maxLength;
}
this.hasMaxLength= function(){
return this.maxLength !== false;
}
}
then I proceed with the following code:
var first_name = new FML_Text("first_name");
first_name.setAsRequired(); /*throws 开发者_JAVA百科an error: setAsRequired is not defined*/
What's wrong? I've checked with the javascript console: first_name is defined but setAsRequired() isn't. The following function calls like first_name.setMaxLength() have no problems.
Thank you in advance.
Thank you in advance
This isn't how you set up inheritance:
function FML_Text(id){
this.prototype= new FML_Field(id);
// ...
}
All that does is create a property called prototype
on the instance.
It's done like this:
function FML_Text(id){
// ...
}
FML_Text.prototype = new FML_Field();
...and you can't pass the id
argument into it, because it happens before the child object constructor is called. Instead, the usual thing is to define an "initializer" function that each level in your hierarchy supports post-construction, and call that.
That's the basics of it, anyway, but really robust inheritance requires more work. For instance, actually making a call to the parent's version of a function that the child also has defined (e.g., a common initializer, or any time a child specializes a parent method) is actually a bit of a fiddle in JavaScript, and there are some other "gotchas" as well. But with a bit of plumbing, you can get very effective inheritance chains (including passing construction-time arguments to parent initializers).
Rather than flying solo, you might want to use one of the existing implementations of this stuff. I describe mine in this article from a while back, which features really efficient calls to parent methods ("supercalls"). The Prototype library also provides an effective "class" system although it was issues with the performance (and compatibility) of that system that lead me to do the article above. Dean Edwards has also written extensively on this subject, and John Resig has pitched in. I had issues with both of those when I looked at them a couple of years ago, but there may have been updates.
Things to look for (in my opinion):
- Straightforward, declarative syntax.
- Syntax that's very friendly to your class having private static members for implementation stuff that doesn't need to be public. (Private instance methods can be done in just about any system, but they're expensive; see Crockford's discussion of them, and my comparison of various ways to achieve them.)
- The system should not rely on function decompilation (using the
toString
method onFunction
instances). Both Prototype's and Resig's do,I don't know about Edwards'as does Edwards'. Function decompilation has never been standardized and doesn't work on some mobile browsers. (In Resig's and Edwards' versions, thetoString
call is implicit, and so it's a bit hard to find, but it's there: They pass a function instance into a regex test, which will implicitly call the function'stoString
.) - The system should not create new function objects on-the-fly when calls to instance methods are made, only when classes are defined (if then). Prototype's does, every time you call an instance method that may need to call its parent's version (their magic
$super
argument). Their mechanism makes it dead easy to use the parent's version, but at the cost (again) of creating a new function on every call whether you actually call$super
or not.
精彩评论