处理self和构造函数参数的Javascript原型

处理self和构造函数参数的Javascript原型,javascript,inheritance,prototype,Javascript,Inheritance,Prototype,我试图理解javascript原型原理,但却无法实现一些基本功能。 我试图实现的一件事是,创建一个基本对象,该对象处理构造函数输入,并基于该输入设置值,如果没有给定构造函数参数,则设置默认值 此外,我还不太明白如何将其存储在变量中,以便它指向正确的对象实例(可能是父对象) 下面是我尝试创建基本继承的两个版本。(我以前见过的第一个,但它不允许我使用扩展对象的基本对象的构造函数来处理传递给扩展对象的构造函数参数。 第二个版本…是我为启用它而提出的,但是…我从未见过任何人使用这样的原型,我确信这是错误

我试图理解javascript原型原理,但却无法实现一些基本功能。 我试图实现的一件事是,创建一个基本对象,该对象处理构造函数输入,并基于该输入设置值,如果没有给定构造函数参数,则设置默认值

此外,我还不太明白如何将其存储在变量中,以便它指向正确的对象实例(可能是父对象)

下面是我尝试创建基本继承的两个版本。(我以前见过的第一个,但它不允许我使用扩展对象的基本对象的构造函数来处理传递给扩展对象的构造函数参数。 第二个版本…是我为启用它而提出的,但是…我从未见过任何人使用这样的原型,我确信这是错误的方式(因为原型属性是一个函数而不是一个对象)

解决这两个问题的正确方法是什么

var Person = function(conf) {
    if (!conf) {conf = {};}
    var _person = this;
    this.first_name = conf.first_name;
    this.last_name = conf.last_name;
    this.greet = function() {
        alert("Hi, im " + this.first_name + " " + this.last_name );
    }
    this.callback_greet = function() {
        alert("Hi, im " + _person.first_name + " " + _person.last_name );
        console.log("this:", this, " _person:", _person );
    }
}

var Student = function(conf) {
    if (!conf) {conf = {};}
    /* id like to pass this conf on to Person constructor */
    this.report = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to study"  );
    }
}
Student.prototype = new Person();

var Teacher = function(conf) {
    if (!conf) {conf = {};}
    this.teach = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to teach...maggots"  );
    }
}
Teacher.prototype = new Person();

student  = new Student({first_name: "Mike", last_name: "Stud"});
//student.first_name="Mike";
//student.last_name="Stud";
student.greet();
/* alerts Hi, im Mike Stud */


teacher  = new Teacher();
teacher.first_name="John";
teacher.last_name="Smith";
teacher.teach();
/* alerts John Smith is ready to teach...maggots */
teacher.callback_greet ();
/* both alerted values are undefined */

//_________________________
//_______Version 2  _______
//_________________________

var Person = function(conf) {
    if (!conf) {conf = {};}
    var _person = this;
    this.first_name = conf.first_name;
    this.last_name = conf.last_name;
    this.greet = function() {
        alert("Hi, im " + this.first_name + " " + this.last_name );
    }
    this.callback_greet = function() {
        alert("Hi, im " + _person.first_name + " " + _person.last_name );
        console.log("this:", this, " _person:", _person );
    }
}

var Student = function(conf) {
    if (!conf) {conf = {};}
    this.prototype = Person;
    this.prototype(conf);
    this.report = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to study"  );
    }
}

var Teacher = function(conf) {
    if (!conf) {conf = {};}
    this.prototype = Person;
    this.prototype(conf);
    this.teach = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to teach...maggots"  );
    }
}

var Principal = function(conf) {
    if (!conf) {conf = {};}
    this.prototype = Teacher;
    this.prototype(conf);
    this.dicipline_teachers = function() {
        alert(  this.first_name + " " + this.last_name + " thy all mighty principal is watching you"  );
    }
}

student  = new Student({first_name: "Mike", last_name: "Stud"});
student.greet();
/* alerts Hi, im Mike Stud */

teacher  = new Teacher({first_name: "John", last_name: "Smith"});
teacher.teach();
/* alerts John Smith is ready to teach...maggots */

principal  = new Principal({first_name: "David", last_name: "Faustino"});
principal.teach();/* alerts David Faustino is ready to teach...maggots */
principal.dicipline_teachers();/* David Faustino thy all mighty principal is watching you*/

嗯,你的第二个版本实际上…有点…正确

你的片段是什么

在这里:

  • 使用
    new Student()调用时,将
    Student
    实例设为
    this
  • 在实例上创建包含函数(在本例中为父构造函数)的属性,该函数实质上在实例上创建方法
  • 将其作为一个方法调用。这意味着,
    Person
    函数被调用,它指向我们这里的实例,然后
    Person
    在该实例上进行设置
  • 这正是我们想要的。可能除了创建不必要的属性之外。请注意,此属性的名称为
    prototype
    与其功能完全无关,您可以使用
    myParentConstructor
    等等

    在标准JavaScript继承中,我们做了一件与方法调用类似的事情——我们希望在当前(子)实例上调用父构造函数,以便对其进行设置


    现在我们还想使用原型。在您的代码中,所有方法
    greet
    report
    teach
    dicipline\u教师可以在实例之间共享,因此他们可以继续。要让所有教师、学生和校长继承这些方法,我们需要建立一个原型链(继承层次结构)。我们会调用构造函数,并在原型对象上设置类似于
    first\u name
    的东西,在原型对象上共享它们,但我们不希望这样。相反,我们使用

    总之,您的代码如下所示:

    function Person(conf) {
        if (!conf) {conf = {};}
        var _person = this;
        this.first_name = conf.first_name;
        this.last_name = conf.last_name;
        this.callback_greet = function() {
            alert("Hi, im " + _person.first_name + " " + _person.last_name );
            console.log("this:", this, " _person:", _person );
        };
    }
    Person.prototype.greet = function() {
        alert("Hi, im " + this.first_name + " " + this.last_name );
    };
    
    function Student(conf) {
        Person.call(this, conf);
    }
    Student.prototype = Object.create(Person.prototype, {constructor:{value:Student}});
    Student.prototype.report = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to study"  );
    };
    
    function Teacher(conf) {
        Person.call(this, conf);
    }
    Teacher.prototype = Object.create(Person.prototype, {constructor:{value:Teacher}});
    Teacher.prototype.teach = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to teach...maggots"  );
    };
    
    function Principal(conf) {
        Teacher.call(this, conf);
    }
    Principal.prototype = Object.create(Teacher.prototype, {constructor:{value:Principal}});
    Principal.prototype.dicipline_teachers = function() {
        alert(  this.first_name + " " + this.last_name + " thy all mighty principal is watching you"  );
    };
    

    嗯,你的第二个版本实际上…有点…正确

    你的片段是什么

    在这里:

  • 使用
    new Student()调用时,将
    Student
    实例设为
    this
  • 在实例上创建包含函数(在本例中为父构造函数)的属性,该函数实质上在实例上创建方法
  • 将其作为一个方法调用。这意味着,
    Person
    函数被调用,它指向我们这里的实例,然后
    Person
    在该实例上进行设置
  • 这正是我们想要的。可能除了创建不必要的属性之外。请注意,此属性的名称为
    prototype
    与其功能完全无关,您可以使用
    myParentConstructor
    等等

    在标准JavaScript继承中,我们做了一件与方法调用类似的事情——我们希望在当前(子)实例上调用父构造函数,以便对其进行设置


    现在我们还想使用原型。在您的代码中,所有方法
    greet
    report
    teach
    dicipline\u教师可以在实例之间共享,因此他们可以继续。要让所有教师、学生和校长继承这些方法,我们需要建立一个原型链(继承层次结构)。我们会调用构造函数,并在原型对象上设置类似于
    first\u name
    的东西,在原型对象上共享它们,但我们不希望这样。相反,我们使用

    总之,您的代码如下所示:

    function Person(conf) {
        if (!conf) {conf = {};}
        var _person = this;
        this.first_name = conf.first_name;
        this.last_name = conf.last_name;
        this.callback_greet = function() {
            alert("Hi, im " + _person.first_name + " " + _person.last_name );
            console.log("this:", this, " _person:", _person );
        };
    }
    Person.prototype.greet = function() {
        alert("Hi, im " + this.first_name + " " + this.last_name );
    };
    
    function Student(conf) {
        Person.call(this, conf);
    }
    Student.prototype = Object.create(Person.prototype, {constructor:{value:Student}});
    Student.prototype.report = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to study"  );
    };
    
    function Teacher(conf) {
        Person.call(this, conf);
    }
    Teacher.prototype = Object.create(Person.prototype, {constructor:{value:Teacher}});
    Teacher.prototype.teach = function() {
        alert(  this.first_name + " " + this.last_name + " is ready to teach...maggots"  );
    };
    
    function Principal(conf) {
        Teacher.call(this, conf);
    }
    Principal.prototype = Object.create(Teacher.prototype, {constructor:{value:Principal}});
    Principal.prototype.dicipline_teachers = function() {
        alert(  this.first_name + " " + this.last_name + " thy all mighty principal is watching you"  );
    };
    

    嗯,你的第二个版本实际上…有点…正确

    你的片段是什么

    在这里:

  • 使用
    new Student()调用时,将
    Student
    实例设为
    this
  • 在实例上创建包含函数(在本例中为父构造函数)的属性,该函数实质上在实例上创建方法
  • 将其作为一个方法调用。这意味着,
    Person
    函数被调用,它指向我们这里的实例,然后
    Person
    在该实例上进行设置
  • 这正是我们想要的。可能除了创建不必要的属性之外。请注意,此属性的名称为
    prototype
    与其功能完全无关,您可以使用
    myParentConstructor
    等等

    在标准JavaScript继承中,我们做了一件与方法调用类似的事情——我们希望在当前(子)实例上调用父构造函数,以便对其进行设置


    现在我们还想使用原型。在您的代码中,所有方法
    greet
    report
    teach
    dicipline\u教师可以在实例之间共享,因此他们可以继续。要让所有教师、学生和校长继承这些方法,我们需要建立一个原型链(继承层次结构)。我们将调用构造函数,并在原型对象上设置类似于
    first\u name
    的内容
    var Constr = function (conf) {
      if (!!conf && !(conf instanceof Object)) {
        throw new Error('An invalid parameter was passed to Constr.');
      }
      if (!conf) { // Prevent "Can't read property 'name' of undefined." 
        conf = {};
      }
      this.name = conf.name || null; // Set defaults this way.
    };
    
    var Person = function (param1, param2) {
      this.param1 = param1;
      this.param2 = param2;
    }
    
    Person.prototype.cough = function () {
      // Do stuff.
    }
    
    var Student = function (param1, param2, paramN) {
      Person.call(this, param1, param2);
      this.paramN = paramN; // Define a new property on the subclass
    }
    
    // Invoke the superclass to have the subclass inherit properties and methods.
    Student.prototype = Object.create(Person.prototype);
    Student.prototype.constructor = Student;