如何在 JavaScript 中克隆构造函数?

4

我有一个构造函数Monkey():

function Monkey(name, age) {
    this.name = name;
    this.age = age;
}

我想创建另一个构造函数,名为Human(),并增加一个额外的属性cars,它将存储人拥有的汽车数量以及所有Monkey拥有的属性(如nameage
我不想在新的Human中重复所有Monkey的内容。是否可以使用原型克隆Monkey并扩展属性?
3个回答

7
我尝试了这段代码,我猜这就是你想要的:
function Human(name,age,cars){
    Monkey.call(this,name,age);
    this.cars = cars;
}

这样,Human 构造函数将 Monkey 构造函数作为一个普通函数进行调用,但是将其命名空间设置为新的 Human 对象。因此,在这种情况下,Monkey 构造函数内部的 this 关键字指的是 Human 类的对象,而不是 Monkey。同时,使用此代码,条件 new Human() instanceof Human; 返回 true,因为我没有返回 Monkey 的新实例,只是使用了它的构造函数。

此外,您可以“克隆”原型,就像您所说的那样。只需执行以下操作:

Human.prototype = Monkey.prototype;

编辑

正如@Bergi amd所建议的,克隆一个原型的最佳方法是使用Object.create方法,如下所示:

Human.prototype = Object.create(Monkey.prototype, {constructor:{value:Human}});

2
Human.prototype = Object.create(Monkey.prototype, {constructor:{value:Human}}); 如果这样做,所有的猴子都会instanceof Human(new Human).constructor将会是猴子。 - Bergi
@Bergi 谢谢,我不知道这个。我会更新答案。 - Danilo Valente
1
实际上,你应该两者都做 - 这样你就可以得到原型上的方法和构造函数的副作用。(或者像@Bergi所说的那样,但如果不支持Object.create,那么就是Human.prototype = new Monkey(); Human.prototype.constructor = Human;)。 - Ry-
@minitech:我确定它的意图是两者兼顾。另外,你不应该使用 Human.prototype = new Monkey - 因为你会得到构造函数中不适用的副作用。有更好的方法可以模拟 Object.create - Bergi
@Bergi:是的,我只是指在这种特殊情况下,因为构造函数除了设置属性之外什么也不做。 - Ry-
还要注意,Human.prototype = Monkey.prototype 并不会以任何方式“克隆”原型对象,它只是意味着 Human.prototype 引用了 Monkey.prototype,这里只有一个对象,没有“克隆”。 - RobG

0

1
是的,但这种方式构造函数返回的是 Monkey 类型的对象,而不是 Human 类型的(参见 new Human() instanceof Human;)。 - Danilo Valente
@MarkLinus "type"? 听起来你把古典思想引入了一个更加动态的领域。依赖于像instanceof这样的东西只会将你束缚在与JavaScript不协调的范式中。 - Matt Whipple
@MarkLinus,你的回答有偏见,而且并不是被问到的问题。像那样使用instanceof是一种编程实现方式。这两个对象提供了相同的功能,而这个解决方案开始时表明它倾向于“函数式”方向,这意味着该对象与数据比类型系统更相似。 - Matt Whipple
这是一种函数/寄生式构造函数,它是使用new关键字的伪经典风格的替代方案。在代码之前有这样的说明。这是一个常见的替代方案,在反对之前应该考虑一下。它要简单得多,并且根据我的经验,可以避免许多具有强大OO背景的人因为原型继承而感到困惑。 - Matt Whipple
你认为那样也可以,但这会赋予new的使用更多的影响力,而实际上并不存在。如果你计划长期处理JS,你应该对两者都感到舒适。我认为你也应该停止提及使用instanceof,因为它可能被用于强制执行契约,这会导致经典层次结构的设计不良,并给JavaScript这样一种动态语言带来虚假的安全感。 - Matt Whipple
显示剩余4条评论

0

其实我认为它根本不应该被使用——继承很奇怪 :-) - Bergi
@Bergi 你是说人类从猴子那里继承了什么吗?我同意 :) 不过,严肃地说,原型结构对我来说并不难以理解。 - Ja͢ck
1
不是的。每个人都是从自己的猴子继承而来的。没有一个人是“Human”的实例,而“Human.prototype”也是无用的。 - Bergi
@Bergi 这很有道理;但某种程度上也是由于问题本身的性质所致。 - Ja͢ck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接