【问题标题】:Javascript parent child inheritance without using prototypeJavascript父子继承不使用原型
【发布时间】:2013-02-01 15:36:29
【问题描述】:

我对 JavaScript 有点陌生。我知道您应该使用原型来实现对象之间的继承,但是我尝试了以下方法并且效果很好(使用 Visual Studio 2012)。我做错了什么?

function Person(firstname, lastname, age, eyecolor) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.age = age;
    this.eyecolor = eyecolor;

    this.name = function() {
        return this.firstname + " " + this.lastname;
    }
}

function Student(firstname, lastname, age, eyecolor, level) {
    this.level = level;
    Person.call(this, firstname, lastname, age, eyecolor);
}

var per = new Person("Abe", "Lincoln", 45, "green");

var obj = new Student("Abe", "Lincoln", 45, "green", "senior");

当我检查 obj 时,它具有 Person 和 Student 的属性,我可以调用 obj.name() 来获取“Abe Lincoln”。即使在 Visual Studio 即时窗口中,我也可以将所有属性视为彼此的兄弟,正如我所期望的那样。但是我没有使用原型,所以显然这是不对的。

请让我直截了当:)

提前致谢!

【问题讨论】:

  • 您正在做的事情更像是“混合”两个课程。 (真的,在谈论 JavaScript 时,“类”这个词本身有些误导。)

标签: javascript inheritance constructor prototype


【解决方案1】:

要使用原型继承,您可以将name 方法放在Person.prototype 上:

function Person(firstname, lastname, age, eyecolor) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.age = age;
    this.eyecolor = eyecolor;
}
Person.prototype.name = function() {
    return this.firstname + " " + this.lastname;
}

然后使Student.prototype对象成为Person的实例:

function Student(firstname, lastname, age, eyecolor, level) {
    this.level = level;
    Person.call(this, firstname, lastname, age, eyecolor);
}

// Make the prototype object of the Student constructor inherit from the
//    prototype object of the Person constructor.
Student.prototype = Object.create(Person.prototype)

所以现在您的 name 方法在所有创建的实例之间共享,而不是为每个实例重新创建。

var per = new Person("Abe", "Lincoln", 45, "green");

var obj = new Student("Abe", "Lincoln", 45, "green", "senior");

【讨论】:

  • 这是我见过的第一个原型继承示例,它实际上按我期望的方式工作。不过,我以为我已经读过无法像那样覆盖.prototype
  • @Alnitak:不,原型对象可以随时更改。使用构造函数创建的任何先前对象仍将引用旧原型对象,但更改后创建的任何对象将使用新对象。您丢失的一件事是原始原型对象上的 .constructor 属性指向构造函数,但如果需要,可以替换它。
  • 谢谢。所以,我对方法使用原型,而不是对属性使用原型,除非我希望属性之一在所有实例中都是静态的,对吗?我是否还要删除 Student 内部的“Person.call(this,...) 调用?还是通过代码示例的最后一行发生这种情况?
  • @user2079283:对。如果值是原始值,您可以将其用于其他属性。当您在实际对象上设置值时,该属性将遮蔽原型对象。您不想将对象和数组放在.prototype 上,因为从构造函数创建的所有对象都可以看到突变。
  • ...不,不要删除Person.call...。这会在每个 Student 对象上调用 Person 构造函数。我添加的只是创建了一个用于继承的空对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-28
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多