为什么在分配DerivedClass.prototype

时间:2015-11-24 11:18:26

标签: javascript inheritance

我一直在阅读使用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给出了另一个理由:

  

当SomeBaseClass有一个函数体时,这将被执行   新关键字。这通常不是意图 - 你只想设置   原型链。在某些情况下甚至可能导致严重的问题   问题,因为你实际上实例化了一个对象,其对象   私有范围的变量由所有MyClass实例共享   继承相同的特权方法。其他副作用是   可想而知。

     

因此,您通常应该更喜欢Object.create。然而,事实并非如此   某些旧版浏览器支持;这就是你看到的原因   新方法过于频繁,因为它往往没有(明显的)伤害。   还看看这个答案。

阅读上述内容似乎更多地取决于所处理的特定情景。 MDN是否有严格的理由说使用new SuperClass()是不正确的?

1 个答案:

答案 0 :(得分:6)

TL; DR 可以使用new Person构建您的Student.prototype,但这样做会使您的所有构造函数复杂化,限制其能力检测构造错误,并要求所有构造函数到处处理这种使用形式。由于它更复杂,容易出错和受到限制,大多数人都走了另一条道路:Object.create

主要的实用问题是:如果超级构造函数需要参数怎么办?说Person需要一个名字:

function Person(name) {
    this.name = name;
}

如何使用new Person创建原型?我没有name来提供它。

现在,有两种方法可以解决这个问题:

  1. 要求所有需要参数的构造函数检测到它们是在没有参数的情况下调用的,假设它们被调用以构建原型,并正确处理该案例。

  2. 请改用Object.create

  3. 这是第一种方式:

    // 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如何检测到它是在没有参数的情况下被调用的,希望这是因为它被用来创建原型而不是出于其他原因,并避免尝试使用缺少的参数。

    这容易出错且很尴尬,这意味着如果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并不需要包含任何特殊情况代码,如果它没有class并且需要它,则可以自由引发错误。

    现在,根据ES2015(又名ES6)的class Student extends Person { constructor(name) { super(name); } } 关键字进行了充分的根深蒂固。这个ES2015代码:

    Object.create

    与上面的<script type="text/javascript"> $(document).ready(function () { $('.myDP').each(function(){ $(this).datepicker({ format: "dd/mm/yyyy", autoclose: true });; }); }); </script> ES5代码非常接近。 (不完全,但非常密切。)