在Node.js的Express模块的代码中,我遇到了这一行,设置了服务器的继承:
Server.prototype.__proto__ = connect.HTTPServer.prototype;
我不确定这是做什么的 - MDC文档(https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_Revisited#prototype_and_ proto )似乎说我可以只是做:
Server.prototype = connect.HTTPServer.prototype;
确实,我做了这个测试:
var parent = function(){}
parent.prototype = {
test: function(){console.log('test')};
}
var child1 = function(){};
child1.prototype = parent.prototype;
var instance1 = new child1();
instance1.test(); // 'test'
var child2 = function(){};
child2.prototype.__proto__ = parent.prototype;
var instance2 = new child2();
instance2.test(); // 'test'
看起来一样吗?所以,是的,我想知道设置object.prototype .__ proto是为了什么。谢谢!
答案 0 :(得分:10)
查看this page(mckoss.com)上的图表,其中显示了小型层次结构的prototype
,constructor
,__proto__
关系。此外,图下方的代码也很好地描述了这种关系。
当你有一个函数Base
,并设置定义的函数对象的原型时,语句Derived.prototype = new Base;
设置__proto__
(实际上是内部[[prototype]]
){自动{1}}到Derived.prototype
,使Derived本身成为可以实例化对象的类。这似乎是一种更符合标准的定义派生类的方法。
根据我的阅读,Base.prototype
是访问对象内部__proto__
的非标准方式。它似乎得到了很好的支持,但我不确定它是否应该被信任。
在任何情况下,您的示例[[prototype]]
似乎以相反的方式进行派生:首先通过定义构造函数和proto来定义对象Server.prototype.__proto__ = connect.HTTPServer.prototype;
,然后挂钩内部{{ 1}}手动将其变形为从Server
派生的类。
至于你建议的替代方案,[[prototype]]
:这是一个坏主意。在这里,您将HTTPServer
的原型设置为与Server.prototype = connect.HTTPServer.prototype;
原型相同的对象。因此,您对Server
课程所做的任何更改都将直接反映在HTTPServer
中,并且可以从Server
的其他派生类中进行更改。如果从HTTPServer
派生的两个类尝试定义相同的成员,则可以对混乱进行图像处理。
答案 1 :(得分:2)
非标准属性__proto__
允许您设置现有对象的原型。
在您的示例中,两个版本都将达到相同的效果,但存在差异:
child1
的原型与parent
的原型相同,而child2
的原型是一个空对象,这个空对象的原型与{{1}相同原型。
当然,由于parent
及其原型没有方法child2
,因此将在原型链中进一步查找此方法。
还要考虑这个:
您只想创建一个应该从另一个对象继承的对象。现在,您可以编写一个构造函数,但JavaScript具有对象文字表示法来直接创建对象,并且您想要使用它。
如果你有一个构造函数,让新对象继承自另一个对象就像设置构造函数的test
一样容易。
显然这对于对象文字不起作用。但在Firefox中,您可以使用prototype
进行设置:
__proto__
由于此属性不是标准属性,因此应避免使用它。