Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
166 views
in Technique[技术] by (71.8m points)

javascript - Prototype copy vs Object.create() vs new

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 = function() {
    document.write("Doing that");
}

function Bird(){
}

// This makes doThat() visible
Bird.prototype = Object.create(Animal.prototype); // Solution 1
// You can also do:
// Bird.prototype = new Animal(); // Solution 2
// Or:
// Bird.prototype = Animal.prototype; // Solution 3

var myVar = new Bird();
myVar.doThat();

As you can see I proposed three solution. Each one of them make the method doThat() visible.

If I comment all of them there is an error indeed.

If I decomment only one of them the program works.

So... what's really the difference between the three solution?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...