我一直在阅读有关使用 Javascript 进行面向对象编程的 MDN 指南,其中在展示继承的示例中提到了以下内容:
// Create a Student.prototype object that inherits from Person.prototype.
// Note: A common error here is to use "new Person()" to create the
// Student.prototype. That's incorrect for several reasons, not least
// that we don't have anything to give Person for the "firstName"
// argument. The correct place to call Person is above, where we call
// it from Student.
Student.prototype = Object.create(Person.prototype); // See note below
我也研究了其他答案,但他们没有具体说明使用 Student.prototype = new Person()
上面提到的一个问题与传递 firstName
有关,但这只是一种情况。
在任何人将其标记为重复之前。这里的问题Using "Object.create" instead of "new"处理通常使用 Object.create
而不是构造函数的问题,而不是我要问的问题。
这里的问题What is the reason to use the 'new' keyword at Derived.prototype = new Base处理 foo()
和 new foo()
这个问题的一个答案JavaScript inheritance: Object.create vs new再给一个理由:
When SomeBaseClass has a function body, this would get executed with the new keyword. This usually is not intended - you only want to set up the prototype chain. In some cases it even could cause serious issues because you actually instantiate an object, whose private-scoped variables are shared by all MyClass instances as they inherit the same privileged methods. Other side effects are imaginable.
So, you should generally prefer Object.create. Yet, it is not supported in some legacy browsers; which is the reason you see the new-approach much too frequent as it often does no (obvious) harm. Also have a look at this answer.
阅读以上内容似乎更多地取决于所处理的给定场景。 MDN 是否有严格的理由说使用 new SuperClass()
是不正确的?
最佳答案
TL;DR 您可以使用 new Person
来构建您的 Student.prototype
,但这样做会很复杂您所有的构造函数,限制了它们检测构造错误的能力,并要求所有地方的所有构造函数都处理这种使用形式。由于它更复杂、更容易出错且有局限性,因此大多数人选择了另一条路:Object.create
。
主要的实用问题是:如果 super 构造函数需要参数怎么办?假设 Person
需要一个名字:
function Person(name) {
this.name = name;
}
我如何使用 new Person
创建我的原型(prototype)?我没有 name
可以提供。
现在,有两种方法可以解决这个问题:
要求所有需要参数的构造函数检测到它们在没有参数的情况下被调用,假设它们被调用以构建原型(prototype),并正确处理这种情况。
改用
Object.create
。
第一种方式:
// NOT WHAT MOST PEOPLE DO
function Person(name) {
if (arguments.length === 0) {
return;
}
this.name = name;
}
function Student(name) {
Person.call(this, name);
}
Student.prototype = new Person;
Student.prototype.constructor = Student;
请注意 Person
必须如何检测到它是在没有参数的情况下被调用的,希望那是因为它被用于创建原型(prototype)而不是出于其他原因,并避免尝试使用缺少的参数.
这很容易出错而且很尴尬,这意味着如果 Person
没有收到最终实例的 name
就不能(例如)引发错误施工电话。它只是不知道为什么要调用它,所以它无法判断没有 name
是否正确。
所以大多数人走另一条路:
// What most people do
function Person(name) {
this.name = name;
}
function Student(name) {
Person.call(this, name);
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Person
不必包含任何特殊情况的代码,如果它没有获得 name
并且需要它,可以自由地引发错误。
现在这已经足够根深蒂固了,它被融入到 ES2015(又名 ES6)的 class
关键字中。这个 ES2015 代码:
class Student extends Person {
constructor(name) {
super(name);
}
}
非常接近上面的 Object.create
ES5 代码。 (不完全是,但相当接近。)
关于javascript - 为什么在分配 DerivedClass.prototype 时使用 Object.create 而不是 new Super,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33892223/