Prototype copy vs Object.create() vs new

前端 未结 2 1165
情话喂你
情话喂你 2020-12-05 22:06

I was using inheritance and I noticed that there are three ways to get the same result. What\'s the difference?

function Animal(){
}

Animal.prototype.doThat         


        
相关标签:
2条回答
  • 2020-12-05 22:25

    You could either use Solution 1 or Solution 2, but you should not use Solution 3.

    The reason is when you do Bird.prototype = Animal.prototype;, every change on Bird.prototype will also affect Animal.prototype, because they the same object.

    For example, you attach a method on Bird.prototype, then the method will also works on Animal, which will not be what you want.

    0 讨论(0)
  • 2020-12-05 22:32

    Bird.prototype = Animal.prototype; // Solution 3

    Since this assigned Animal.prototype directly to Bird.prototype, all changes you make to the latter will also be reflected in Animal and all other classes that inherit from it.

    For example:

    Bird.prototype.fly = function() {
        console.log('I can fly.');
    }
    
    var some_animal = new Animal();
    some_animal.fly(); // this will work
    

    This is certainly not what you want. Not only will every method of this subclass available for other subclasses, but if you override parent methods in subclasses, the subclass that was defined last will override the changes of the other subclasses.

    In your question title you seem to refer to this as "prototype copy". This is not correct, since no copy is created. Animal.prototype and Bird.prototype will refer to one and the same object.


    Bird.prototype = new Animal(); // Solution 2

    This has been a common way to setup inheritance for a long time but it has two major drawbacks:

    • If Animal requires arguments, which do you pass? Passing random, meaningless arguments just to make the function call work seems to be bad design.
    • Animal might have side effects, like increasing an instance counter, but in this moment you actually didn't create a new instance (or don't want to), you just wanted to setup the inheritance.

    Bird.prototype = Object.create(Animal.prototype); // Solution 1

    That's the way you should do it now (until a better solution comes). All you really want to do is hook up Animal's prototype into the prototype chain of Bird. It avoids all the drawbacks of the previous solutions.

    To make it work properly though, you also have to call the Animal constructor inside the Bird constructor. It's like a call to super in other programming languages:

    function Bird(){
        Animal.call(this);
    }
    

    This ensure that any commands/changes made to a new Animal instance are applied to the new Bird instance.

    It is also good practice to assign the correct value to the constructor property of the prototype. It usually refers to the function the prototype "belongs to", but in all of the solutions above, Bird.prototype.constructor will refer to Animal. So we have to do:

    Bird.prototype.constructor = Bird;
    

    This property is not used internally, so you only have to do this if your own code relies on it. However, if you create a library to be used by others, they will probably expect the property to have to correct value.

    0 讨论(0)
提交回复
热议问题