原型副本 vs Object.create() vs new [英] Prototype copy vs Object.create() vs new

查看:31
本文介绍了原型副本 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();

如您所见,我提出了三种解决方案.它们中的每一个都使 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?

推荐答案

Bird.prototype = Animal.prototype;//方案三

由于此将 Animal.prototype 直接分配给 Bird.prototype,您对后者所做的所有更改也将反映在 Animal 和从它继承的所有其他类.

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.

例如:

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.

在您的问题标题中,您似乎将其称为原型副本".这是不正确的,因为没有创建副本.Animal.prototypeBird.prototype 将引用同一个对象.

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();//方案二

长期以来,这一直是设置继承的常用方法,但它有两个主要缺点:

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

  • 如果 Animal 需要参数,你传递哪个参数?仅仅为了使函数调用起作用而传递随机的、无意义的参数似乎是糟糕的设计.
  • Animal 可能有副作用,例如增加实例计数器,但此时您实际上并没有创建新实例(或不想创建),您只是想设置继承.
  • 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);//方案一

这就是你现在应该这样做的方式(直到出现更好的解决方案).您真正想要做的就是将Animal 的原型连接到Bird 的原型链中.它避免了以前解决方案的所有缺点.

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.

为了使其正常工作,您还必须在 Bird 构造函数中调用 Animal 构造函数.这就像在其他编程语言中调用 super 一样:

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);
}

这确保对新 Animal 实例所做的任何命令/更改都应用于新的 Bird 实例.

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

为原型的 constructor 属性分配正确的值也是一种很好的做法.它通常指原型所属"的函数,但在上述所有解决方案中,Bird.prototype.constructor 将指代Animal.所以我们必须这样做:

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.

这篇关于原型副本 vs Object.create() vs new的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆