第一步是理解constructor
和prototype
都是关于。这并不难,但我们必须放弃古典意义上的“继承”。
构造函数
这个constructor
财产不导致程序中的任何特殊效果,除非您可以查看它以查看与运算符一起使用的函数。new
来创建你的对象。如果你打字new Bar()
它将是Bar
你打字new Foo
它将是Foo
.
原型
这个prototype
属性用于在所述对象没有所请求的属性的情况下进行查找。如果你写x.attr
,JavaScript将试图找到attr
在x
的属性。如果它找不到它,它将查找x.__proto__
..如果它也不在那里,它就会往里面看x.__proto__.__proto__
等等只要__proto__
被定义。
所以什么是__proto__
它和这件事有什么关系prototype
?不久,prototype
代表“类型”__proto__
代表“实例”。(我这样说是用引号表示的,因为类型和实例实际上没有任何区别)。当你写x = new MyType()
,发生的事情(除其他外)是x.__proto___
设置为MyType.prototype
.
问题
现在,您只需通过上面的内容来推导出您自己的示例的含义,而是尝试回答您的实际问题;“为什么要写类似的东西”:
Bar.prototype.constructor = Bar;
我个人从未见过它,我觉得它有点傻,但在你给出的上下文中,这意味着Bar.prototype
-对象(通过使用new Foo(42)
)将摆出已经被创造出来的姿势。Bar
而不是Foo
..我想这个想法是一些类似于C+/Java/C#的语言,其中类型查找(constructor
属性)总是会产生最特定的类型,而不是原型链中更高的泛型对象的类型。
我的建议是:不要过多地考虑JavaScript中的“继承”。接口和混合的概念更有意义。也不要检查对象的类型。检查所需的属性(“如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那就是鸭子”)。
试图将JavaScript强制进入一个经典的继承模型,而它所拥有的只是上面描述的原型机制,这就是造成混乱的原因。建议手动设置constructor
-财产可能就是这样做的。抽象是可以的,但是构造函数属性的手动分配并不是JavaScript的惯用用法。