在派生的旧式构造函数中应该如何设置 `.prototype` 属性?

问题描述 投票:0回答:3

我不敢问这个问题,因为同一主题已经有很多人了。

我试图了解使用

approach-1
approach-2

的缺点/限制
function Person(name, age) {
  this.name = name || "de-name";
  this.age = !!Number(age) ? Number(age) : 0;
}

Person.prototype.setName = function(name) {
  this.name = name;
  return this;
}

function Student(name) {
  Person.call(this, name); // Copy instance properties of Person class
  this.title = "Student";
}

// Suggested way
Student.prototype = Object.create(Person.prototype);


// Possible approach-1
// Student.prototype = Person.prototype;   

// Possible approach-2
// Student.prototype = new Person();
javascript inheritance prototype
3个回答
1
投票

在基于原型的语言中,继承是通过克隆充当原型而不是类的现有对象来执行的。

因此,在每种情况下,我们都应该考虑选择用作原型的对象来弄清楚其行为。

在方法 1 中,您将

Student
的原型设置为与
Person
相同的原型对象。这意味着对
Student.prototype
所做的任何更改都会影响
Person.prototype
,反之亦然。

在方法 2 中,您将

Student
的原型设置为一个新的 Person 对象,该对象将根据您的初始化代码设置以下属性
{name: 'de-name', age: 0}
。 然后,您在
Person.call()
函数中调用
Student
将会覆盖 name 属性。由于这是一个全新的对象,对
Student.prototype
的任何修改只会影响新的 Student 对象,并且作为原型的此
Person
实例上任何缺失的属性都将委托给
Person.prototype

为了详细说明最后一点(缺少的属性将在原型链上传递),这里有一个示例。假设我们向

greet
添加一个新方法
Person
:

Person.prototype.greet = function() { console.log("Hi! " + this.name; ) }

调用

new Student().greet()
将使 JavaScript 检查原型链,直到它命中适当的属性(否则您会收到未定义的错误。)

// Walking up the chain
/* 1 */ new Student()     // doesn't have a greet property
/* 2 */ Student.prototype // => Person {name: 'de-name', age: 0}
// This person instance doesn't have a greet property either
// because we instantiated it before adding the `greet` property
/* 3 */ Person.prototype  // Has a greet property which gets called

在使用

Object.create
的建议模式中,您所做的事情几乎与
Student.prototype = new Person()
相同,只是
Object.create
允许您执行 差异继承。您甚至可以添加其他属性作为其第二个参数:

Student.prototype = Object.create(Person.prototype, {
  age: 16,
  study: function() { console.log("But I'm sooo lazy!!!"); } 
});

0
投票

approach-2 表示原型链中多了一个对象。如果

(new Student()).someAttr
在学生对象 (
new Student()
) 中未解析,则使用方法 2,检查人员对象 (
new Person()
)(因为这就是
Student.prototype
中的内容),然后检查
Person.prototype
。使用方法 1,就没有 person 对象。


0
投票

方法1和方法2实际上并不完全一样。在方法 2 中,您将创建

Person
的新实例,并将该新实例分配给 Student 的原型。

此外,你应该这样做:

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

根据MDN

Object.create() 方法使用指定的原型对象和属性创建一个新对象。

因此,您不将其分配给 Student 原型,而是将其分配给 Student 本身,Student 将 Person 作为其原型。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.