为什么需要设置原型构造函数?
在MDN文章面向对象Javascript简介中关于继承的部分,我注意到他们设置了protype.constructor:
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
这有什么重要目的吗?可以省略它吗?
在MDN文章面向对象Javascript简介中关于继承的部分,我注意到他们设置了protype.constructor:
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
这有什么重要目的吗?可以省略它吗?
它并不总是必要的,但它确实有其用途。假设我们要在基类上创建一个复制方法。喜欢这个:Person
// define the Person Class
function Person(name) {
this.name = name;
}
Person.prototype.copy = function() {
// return new Person(this.name); // just as bad
return new this.constructor(this.name);
};
// define the Student class
function Student(name) {
Person.call(this, name);
}
// inherit Person
Student.prototype = Object.create(Person.prototype);
现在,当我们创建一个新的并复制它时会发生什么?Student
var student1 = new Student("trinth");
console.log(student1.copy() instanceof Student); // => false
副本不是 的实例。这是因为(如果没有显式检查),我们将无法从“基”类返回副本。我们只能返回 .但是,如果我们重置了构造函数:Student
Student
Person
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
...然后一切按预期工作:
var student1 = new Student("trinth");
console.log(student1.copy() instanceof Student); // => true
这有什么重要目的吗?
是和否。
在ES5及更早版本中,JavaScript本身并没有用于任何事情。它定义了函数属性上的默认对象将具有它,并且它将引用回函数,仅此而已。规范中根本没有其他任何内容提及它。constructor
prototype
这在ES2015(ES6)中发生了变化,它开始在继承层次结构中使用它。例如,Promise#然后在
构建返回的新 promise 时使用您调用它(通过 SpeciesConstructor)的承诺的属性。它还参与子类型化数组(通过ArraySpeciesCreate)。constructor
在语言本身之外,有时人们在尝试构建通用的“克隆”函数时会使用它,或者只是在他们想要引用他们认为是对象的构造函数时使用它。我的经验是,使用它很少见,但有时人们确实使用它。
可以省略它吗?
默认情况下,它在那里,只需在替换函数属性上的对象时将其放回原处:prototype
Student.prototype = Object.create(Person.prototype);
如果不这样做:
Student.prototype.constructor = Student;
...然后继承(大概)具有 .所以这是误导性的。当然,如果你正在子类化使用它的东西(如或),而不是使用¹(它为你处理这个问题),你需要确保你设置正确。所以基本上:这是一个好主意。Student.prototype.constructor
Person.prototype
constructor = Person
Promise
Array
class
如果您的代码(或您使用的库代码)中没有任何内容使用它,则没关系。我一直确保它已正确连接。
当然,对于ES2015(又名ES6)的关键字,大多数时候我们会使用它,我们不必再使用它了,因为当我们这样做时,它会为我们处理。class
class Student extends Person {
}
¹ “...如果你正在子类化使用它的东西(如Promise
或Array
)而不是使用class
......“——这是可能的,但这是一个真正的痛苦(而且有点傻)。你必须使用Refle.construct
。