父类的方法在javascript中的子类中未定义

时间:2011-04-22 08:40:08

标签: javascript oop


我是js OO编程的新手,我找不到这个错误的解决方案。 我声明了以下类层次结构:

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;
    };
}

及其儿子:

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;
    }
}

然后我继续下面的代码:

var first_name = new FML_Text("first_name");
first_name.setAsRequired(); /*throws an error: setAsRequired is not defined*/

怎么了?我已经使用javascript控制台检查:first_name已定义但setAsRequired()未定义。以下函数调用如first_name.setMaxLength()没有问题。

提前谢谢。

提前谢谢

1 个答案:

答案 0 :(得分:0)

这不是你设置继承的方式:

function FML_Text(id){
    this.prototype= new FML_Field(id);
    // ...
}

所有这一切都是在实例上创建一个名为prototype的属性。

这样做:

function FML_Text(id){
    // ...
}
FML_Text.prototype = new FML_Field();

...并且您无法将id参数传递给它,因为它发生在调用子对象构造函数之前。相反,通常的做法是定义一个“初始化器”函数,层次结构中的每个级别都支持构造后,并调用它。

无论如何,这是它的基础,但真正强大的继承需要更多的工作。例如,实际上调用父级已经定义的函数的父版本(例如,一个公共的初始化程序,或者一个孩子专门研究父方法的任何时候)实际上是JavaScript中的一个小提琴,并且有其他一些“陷阱”。但是通过一些管道,你可以获得非常有效的继承链(包括将构造时参数传递给父初始化器)。

您可能希望使用此内容的现有实现之一,而不是单独飞行。我在前一段时间内在this article中描述了我的内容,其中包含对父方法(“supercalls”)的高效调用。 Prototype库也提供了一个有效的“类”系统,尽管这个系统的性能(和兼容性)问题导致我做上面的文章。 Dean Edwards也在这个主题上撰写了大量文章,并且John Resig已经投入。我几年前看过这些文章时遇到了两个问题,但可能有更新。

要寻找的东西(在我看来):

  • 直截了当,声明性语法。
  • 对您的类非常友好的语法,具有私有静态成员,用于实现不需要公开的内容。 (私有实例方法几乎可以在任何系统中完成,但它们很昂贵;请参阅Crockford's discussion,以及my comparison各种方法来实现它们。)< / LI>
  • 系统依赖于函数反编译(使用toString实例上的Function方法)。 Prototype和Resig都做了,我不像爱德华兹那样了解爱德华兹的。函数反编译从未标准化,并且在某些移动浏览器上不起作用。 (在Resig和Edwards的版本中,toString调用是隐式的,所以它有点难以找到,但它就在那里:它们将函数实例传递给正则表达式测试,它将隐式调用函数的{{1 }}。)
  • 系统应该在调用实例方法时动态创建新的函数对象,仅在定义类时(如果是)。 Prototype's,每次你调用一个可能需要调用其父版本的实例方法(他们的魔法toString参数)。他们的机制使得使用父版本很容易,但不管是否实际调用$super,都需要(再次)在每次调用时创建一个新函数