【问题标题】:Inheritance within JavascriptJavascript 中的继承
【发布时间】:2013-03-28 10:37:54
【问题描述】:

我正在研究Javascript中继承的概念,我正在看的教程使用了这段代码:

// define the Student class
function Student() {
  // Call the parent constructor
  Person.call(this);
}

// inherit Person
Student.prototype = new Person();

// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;

我的问题是,为什么必须同时调用父构造函数Person.call(this),并将Student 原型设置为等于新的Person 对象(即Student.prototype = new Person();)?

【问题讨论】:

标签: javascript inheritance


【解决方案1】:

在做了一些测试之后,据我了解,对象的原型和在其定义函数中所做的属性声明是分开的。但是,当构造一个新对象时,构造函数将从定义函数和正在创建的对象的原型中提取属性。

例如,

function Person()
{

    this.name = "james";
    this.age = "shfifty-five";


}

console.log(Person.prototype.name); // prints "undefined", showing how declaring function Person() and Person.prototype are separate.

Person.prototype.gender = "male";

var human = new Person();

console.log(human.name); // prints "james", showing how the object took properties from declaring function Person().
console.log(human.gender); // prints "male", showing how the object took properties from object prototype Person.prototype.


function Student()
{

    this.gpa = 4.00;


}



Student.prototype = new Person();

Student.prototype.constructor = Student;


var myStudent = new Student();

console.log(myStudent.name); // prints "james"
console.log(myStudent.gender); // prints "male"
/*from above two lines, inheritance holds even though 1) Person() defining function was not called inside Student() defining function
and 2) Person() defining function declares properties of Person object.*/
console.log(myStudent.gpa); // prints "4"

如您所见,在这种情况下,定义函数 Person 确实改变了其对象的属性。但是仍然没有必要在 Student 的构造函数中调用 Person 函数,因为 new Person() 构造函数将从 Person.prototypefunction Person() 定义函数中提取属性。

【讨论】:

  • 这取决于...每个新的Student 对象都将继承Student.prototype 对象的属性。在您的示例中,当您执行Student.prototype = new Person() 时,会向正在分配的Person 对象添加一些属性,因此这些属性自然会被继承。但是,如果在Person 构造函数中分配的值不是静态的怎么办?如果您不对新的Student 对象调用Person,它们将始终引用在原型对象上设置的相同属性值。如果你确实想要继承静态值,你应该把它们放在Person.prototype
【解决方案2】:

有两个不同的问题需要处理。

首先是确保新的Student 对象继承自Person 对象。这就是为什么你这样做Student.prototype = new Person()。这使得Student.prototype 成为Person 所以Student 对象将继承该对象继承的任何内容(来自Person.prototype

第二个是将Person 构造函数中的任何行为应用于任何新的Student 对象。这就是为什么你这样做Person.call(this)。如果Person 构造函数没有任何修改新对象的代码,这在技术上是不需要的,但这样做仍然是一个好主意,以防您稍后向Person 添加一些代码。


旁注,设置继承时,最好这样做:

Student.prototype = Object.create(Person.prototype)

...和垫片Object.create 如果需要。这样,您实际上不需要调用Person 构造函数来获取继承自Person.prototype 的新对象。同样,有时不是问题,但有时在构造函数中会出现在设置继承时不希望出现的副作用。

【讨论】:

  • 我只是好奇...设置原型的构造函数的原因是什么? Student.prototype.constructor = Student;
  • +1 用于修复删除new Person(),如果父构造函数有参数,这可能会出现问题。同样在构造函数中,也可以发送参数。
  • @Polaris878: 这是因为默认的Student.prototype 对象有一个.constructor 属性指向Student 函数...但是该对象正在被替换,所以如果.constructor 属性是需要的,需要手动添加到新对象中。
  • 但是我们不是有效地调用了构造函数两次吗? Person.call(this) 和 new Person() 有什么区别?为什么对象的定义函数中对对象的更改没有反映在对象的原型中?
  • @voltair: new Person 用于创建新对象。 Person 函数中的新对象由this 引用。当我们执行Person.call(this) 时,我们将获取当前的this,这是新的Student 对象,并手动将其设置为Person 函数的this 值。这么说吧……在 JavaScript 中,继承几乎与构造函数无关。当一个对象从另一个对象继承时,不会自动调用构造函数。构造函数只是在两个对象之间建立原型关系的一种奇怪而令人困惑的方式。
猜你喜欢
  • 2011-01-02
  • 1970-01-01
  • 2013-11-07
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
相关资源
最近更新 更多