Javascript中的继承
当我使用原型在Javascript中实现继承时,我遇到了一个奇怪的错误。我想知道是否有人能解释这一点。在下面的代码中, 我正在尝试从父类派生子类:Javascript中的继承,javascript,internet-explorer,firefox,Javascript,Internet Explorer,Firefox,当我使用原型在Javascript中实现继承时,我遇到了一个奇怪的错误。我想知道是否有人能解释这一点。在下面的代码中, 我正在尝试从父类派生子类: parent_class=function(byref) { if( !parent_class.prototype._vtbl ) { parent_class.prototype.p
parent_class=function(byref)
{
if( !parent_class.prototype._vtbl )
{
parent_class.prototype.parent_func= function(o) { return alert("parent_func"); }
parent_class.prototype._vtbl = true;
}
}
child=function(byref)
{
parent_class.call(this,byref);
if( !child.prototype._vtbl )
{
child.prototype = new parent_class;
child.prototype.child_func = parent_class.prototype.parent_func;
child.prototype._vtbl = true;
}
}
function dotest()
{
var pub = new child;
alert( pub.child_func );
var pub2 = new child;
alert( pub2.child_func );
}
dotest();
在浏览器(Firefox或IE)中运行测试时,会收到两个警报。第一个表示pub.child_func未定义,第二个表示pub.child_func是有效函数,并且是parent_class.parent_func。你为什么会看到这种行为。这是一个bug吗?这种结构的javascript执行顺序:
function SomeClass () { body(); }
var x = new SomeClass();
这是:
SomeClass.prototype
继承的新对象已创建(在执行构造函数的代码之前,在此选择对象的原型)body()代码>被执行
child = function (byref) {
parent_class.call(this, byref);
if (!child.prototype._vtbl) {
child.prototype = new parent_class;
child.prototype.child_func = parent_class.prototype.parent_func;
child.prototype._vtbl = true;
}
this.__proto__ = child.prototype;
}
你真正应该做的是:
child = function (byref) {
parent_class.call(this, byref);
}
child.prototype = Object.create(parent_class.prototype);
child.prototype.child_func = parent_class.prototype.parent_func;
child.prototype._vtbl = true;
执行JavaScript继承的一种更简单的方法可能是工厂模式:
function Animal(name) {
return {
run: function() {
alert(name + " is running!")
}
}
}
var animal = Animal("fox");
animal.run();
function Rabbit(name) {
var rabbit = Animal(name);
rabbit.bounce = function() {
this.run();
console.log(name + " bounces");
}
return rabbit;
}
var rabbit = Rabbit("rabbit");
rabbit.bounce();
来源:简短回答:不,这不是浏览器错误,这是预期行为 详细答案: 当使用
new
调用构造函数时,对其原型的引用将复制到对象的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
中。稍后,此属性用于此对象的原型查找
从javascript开发人员的角度来看,当您在构造函数调用执行期间修改构造函数的prototype
时,您的代码非常奇怪。然而,它是有效的。因为,在var parent=new parent_class()之后代码>以下是正确的父级。uuu proto_uuu===parent\u class.prototype
。这是相同的参考。因此,将属性添加到parent_类中。prototype
会通过原型查找在parent
对象中自动重新影响。
不幸的是,我还不能发表评论,所以我必须从我的回答中引用,@RyszardFiński说,prototype
是在构造函数调用之前定义的,之后不能更改,这不是一个正确的说法。它是同一个对象,除非您更改引用,否则所有实例化对象的更改将立即反映出来
但是,在child
中,当child.prototype
分配给新对象时,OP中的code会破坏引用
child.prototype=新的父类代码>
child.prototype
开始指向父类(#1)的新实例。实例引用如下所示
pub.__proto__ === child.prototype
pub2.__proto__ === parentInstance1
child.prototype === parentInstance2
如果删除分配了child.prototype
的代码行,所有内容都将按预期开始工作
pub.__proto__ === child.prototype
pub2.__proto__ === child.prototype
child.prototype === child.prototype
child.prototype has properties _vtbl and child_func
这是代码中的一个bug。不要在构造函数中初始化原型!如果您想使用工厂模式,以便在不使用new
(如rabbit=Animal(name);
)的情况下调用函数,那么您不能使用此
。您是对的,严重的复制和粘贴错误…已修复,谢谢您指出。您的建议有效。我现在明白为什么了。但这是否意味着这是一个可接受的替代方案?Bergi指出的讨论似乎不是决定性的。真正的目标是找到一种方法,使函数表不是每次都重新创建,而是只重新创建一次。实现这一点的最佳方法是什么?虽然我的帖子是对你最初的确切问题(它的表述方式)的确切回答,但我认为这不是一个很好的继承方法。对于使用私有变量的函数,无法实现单个函数表,但是可以将它们复制到新对象的原型中。因为JS中的继承是原型而不是经典。如果你真的想在这方面有点学术性,我建议你仔细阅读