我不敢问这个问题,因为同一主题已经有很多人了。
我试图了解使用
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();
在基于原型的语言中,继承是通过克隆充当原型而不是类的现有对象来执行的。
因此,在每种情况下,我们都应该考虑选择用作原型的对象来弄清楚其行为。
在方法 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!!!"); }
});
approach-2 表示原型链中多了一个对象。如果
(new Student()).someAttr
在学生对象 (new Student()
) 中未解析,则使用方法 2,检查人员对象 (new Person()
)(因为这就是 Student.prototype
中的内容),然后检查 Person.prototype
。使用方法 1,就没有 person 对象。
方法1和方法2实际上并不完全一样。在方法 2 中,您将创建
Person
的新实例,并将该新实例分配给 Student 的原型。
此外,你应该这样做:
var Student = Object.create(Person.prototype);
根据MDN:
Object.create() 方法使用指定的原型对象和属性创建一个新对象。
因此,您不将其分配给 Student 原型,而是将其分配给 Student 本身,Student 将 Person 作为其原型。