【问题标题】:why do we need to call the parent constructor in JavaScript Inheritance为什么我们需要在 JavaScript 继承中调用父构造函数
【发布时间】:2012-02-23 08:49:44
【问题描述】:

我正在试验 JavaScript 继承。基本上,我正在关注this 教程。

我看到,使用那里的代码,Person 类被实例化了两次。请看this fiddle。

我所做的是注释掉:

Person.call(this)

继承工作得很好。

在原代码中,一行

Person.call(this)

被使用。是否需要调用具有子作用域的父构造函数?

能否请您解释一下,我是 OO JavaScript 新手。

非常感谢。

编辑:

我在小提琴中的代码如下:

function Person(gender) {
    this.gender = gender;
    document.write('Person instantiated</br>');
}

Person.prototype.walk = function(){
    document.write("is walking</br>");
};

Person.prototype.sayHello = function(){
    document.write("Hello</br>");
};

Person.prototype.sayGender = function(){
    document.write(this.gender + "</br>");
};



function Student() {
    //Person.call(this);
    document.write('Student instantiated</br>');        
}
Student.prototype = new Person();

Student.prototype.constructor = Student;

Student.prototype.sayHello = function(){
    document.write("Student says Hello</br>");
}
Student.prototype.sayGoodBye = function(){
    document.write("Student says goodbye</br>");
}


var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();

document.write(student1 instanceof Person);
document.write("</br>");
document.write(student1 instanceof Student);

【问题讨论】:

  • @T.J.Crowder:对不起,如果我的问题的语气有问题。我从没想过粗鲁。
  • @hrishikeshp19:不,我认为你没有。 :-)

标签: javascript inheritance prototype


【解决方案1】:

是的,您将需要它。在您的示例中,所有学生都具有相同的性别,并且无论实例化的学生数量如何,都只会实例化一个 Person。

更好的是:

function Student() {
    // gives this Student properties of one (new) Person:
    Person.call(this);
    document.write('Student instantiated</br>');        
} 
// does not create a Person, just makes Students have Person prototype features
Student.prototype = Object.create(Person.prototype);

【讨论】:

  • 这个答案应该被接受。有人问我们为什么需要做Person.call(this);,它回答了这个问题。尝试在Person.call(this); 之前放置一个debugger 并查看this 的值(学生);你会发现它之前没有gender属性,但是一调用parent就得到了。
【解决方案2】:

运行您提供的示例仅在脚本的初始执行期间调用 Person() 构造函数一次,当行“Student.prototype = new Person();”时被执行。

如果我们修改您的脚本以创建第二个学生并将设置与实例化分开:bit: http://jsfiddle.net/anacW/

function Person(gender) {
    this.gender = gender;
    document.write('Person instantiated</br>');
}

Person.prototype.walk = function(){
    document.write("is walking</br>");
};

Person.prototype.sayHello = function(){
    document.write("Hello</br>");
};

Person.prototype.sayGender = function(){
    document.write(this.gender + "</br>");
};



function Student() {
    //Person.call(this);
    document.write('Student instantiated</br>');        
}
Student.prototype = new Person();

Student.prototype.constructor = Student;

Student.prototype.sayHello = function(){
    document.write("Student says Hello</br>");
}
Student.prototype.sayGoodBye = function(){
    document.write("Student says goodbye</br>");
}

document.write("*** Building student1 *** </br>");
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();

document.write("*** Building student2 ***</br>");
var student2 = new Student();
student2.sayHello();
student2.walk();
student2.sayGoodBye();

document.write("*** InstanceOf Tests ***</br>");
document.write("student1 is Person?: " + (student1 instanceof Person));
document.write("</br>");
document.write("student1 is Student?: " + (student1 instanceof Student));
document.write("</br>");
document.write("student2 is Person?: " + (student2 instanceof Person));
document.write("</br>");
document.write("student2 is Student?: " + (student2 instanceof Student));

​

这段代码给出:

Person instantiated
*** Building student1 *** 
Student instantiated
Student says Hello
is walking
Student says goodbye
*** Building student2 ***
Student instantiated
Student says Hello
is walking
Student says goodbye
*** InstanceOf Tests ***
student1 is Person?: true
student1 is Student?: true
student2 is Person?: true
student2 is Student?: true

这表明 Person 构造函数只被调用一次,并且永远不会通过实例化 Student 来调用。在您的情况下,这可能是可取的(我不知道足够的 javascript 来告诉您它是否是“正确”的形式)。

【讨论】:

  • 我不知道任何情况下这是可取的;通常它会导致错误(只要示例不是太简单)。该代码结构有一些情况,但不是在oo继承中。
【解决方案3】:

我是如何做到的:

Foo = function() {}
Foo.prototype.sayHello = function() { console.log("hello"); }

Bar = function() {}
Bar.prototype = new Foo();
Bar.prototype.sayBye = function() { console.log("bye"); }

var oBar = new Bar();
oBar.sayHello(); // "hello"
oBar.sayBye(); // "bye"

【讨论】:

  • 是的。但是,在这种方法中,永远不会调用 Bar 的构造函数。因此,为“酒吧”保留任何私有内容是没有意义的。所以,Bar 永远不会被初始化,你使用的只是 Foo 对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 2015-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多