【发布时间】:2016-01-18 11:21:55
【问题描述】:
我知道原型继承的经典模式是基于设置构造函数的对象原型。 但是我愿意有可能从派生类构造函数中调用父构造函数,其中一些参数在调用之前不可用。
这在 Java/Python/PHP 中使用 super(...) 或 Parent.__init__(...) 方法可以很好地完成。
但是在纯 Javascript(不是 coffescript 或类似的)中没有办法做到这一点(parent.apply(this,arguments) 可以,但它不会设置原型)。
经过一些阅读,我得到了这个解决方案,将“继承”方法添加到 Function 的原型中。 这只是将 super 的定义添加到派生函数中,以便根据一些参数初始化原型。
Function.prototype.inherits=function(parent)
{
var ctor=this;
var p=Object.create(parent);
ctor.super=function()
{
parent.apply(p,arguments);
}
ctor.prototype=p;
}
//testing
function A(x)
{
this.x=x;
}
function B(y)
{
B.super(y*2);//Here "super" is available and I can pass parameters.
this.y=y;
}
B.inherits(A);//here I define the inheritance
a=new A(3);
b=new B(5);
console.log(a);//returns { x: 3 }
console.log(b);//returns { y: 5 }
console.log(b.x);//returns 10
console.log(a instanceof A);//returns true
console.log(b instanceof B);//returns true
通过这种方式,我得到了我所期望的行为。 我的问题是:这个解决方案有什么缺点?同一个问题有更有效的解决方案吗?此解决方案是否跨浏览器?
PS:我自己发明的:)
编辑:为了避免与其他库发生冲突,我可以定义一个像这样实现相同目标的独立函数。
function inherits(klass,parent)
{
var p=Object.create(parent);
klass.super=function()
{
parent.apply(p,arguments);
}
klass.prototype=p;
}
并且在定义B之后的测试中简单地调用
inherits(B,A);
编辑 2:
在 Moolamaduck 考虑之后,我重写了代码以解决共享原型的问题。结果非常简单易用且优雅(恕我直言)。
https://stackoverflow.com/a/33270707/76081
【问题讨论】:
-
一个缺点是您正在修改内置对象,这通常被认为(有充分理由)是不好的做法。修改函数/数组/对象等的原型是一个糟糕的(或至少是脆弱的)想法。在效率方面,如果您的对象创建是您的瓶颈,那么您几乎可以肯定做错了。跨浏览器?除非你需要支持旧的 IE,否则没问题。
-
效率以什么指标衡量?运行?代码复杂性/可维护性?
-
另外,您对转译器有什么强烈反对吗? Coffeescript、babel 和 traceur 都可以处理
super就好了。还是更多的是出于教育目的? -
是的,速度和内存的效率。
-
它非常正确,除了不完整之外没有其他重要缺陷。例如,它处理子类化
Array的效果如何?Date怎么样?RegExp?如果您只想继承您自己的用户定义的构造函数,那么我认为您会发现您的版本易于维护,并且具有上述警告的充足性能。
标签: javascript inheritance prototype super default-constructor