扩展Javascript类和继承
好的,所以我一直在试图找到一种方法,使普通的老Javascript像许多其他OOP语言一样具有某种扩展继承。但我遇到了一个特定的问题,当一个类使用原型扩展父类时,该对象的每个子对象都共享变量,而不是拥有自己的父对象的新实例。例如:扩展Javascript类和继承,javascript,class,prototype,Javascript,Class,Prototype,好的,所以我一直在试图找到一种方法,使普通的老Javascript像许多其他OOP语言一样具有某种扩展继承。但我遇到了一个特定的问题,当一个类使用原型扩展父类时,该对象的每个子对象都共享变量,而不是拥有自己的父对象的新实例。例如: TestB.prototype = new TestA(); function TestB(){ } function TestA(){ var num = 0; this.count = function(){ num ++
TestB.prototype = new TestA();
function TestB(){ }
function TestA(){
var num = 0;
this.count = function(){
num ++;
console.log(num);
}
}
var test = new TestB();
test.count();
var test2 = new TestB();
test2.count();
因此,当代码运行时,控制台如下所示:
1
2
其中,我希望从父类继承的“num”变量对于每个实例都是唯一的,因此输出应该是:
1
1
我假设发生这种情况是因为当调用prototype时,它只创建一个TestA的新实例,而不是每次调用TestB的构造函数都创建一个。问题是,我没有找到另一种方法使它工作
感谢您的帮助(请注意,这实际上是为了更具体的用途,但我只想创建一个超级简单的测试用例来清楚地说明问题。我没有自由使用外部库(如jQuery或prototype.js)来解决问题)您不应该在构造函数中定义方法,而应该在原型中定义方法。这样可以节省内存 ,性能更好,并允许干净地扩展类
function TestA() {
this.num = 0;
}
TestA.prototype = {
count: function() {
console.log( this.num++ );
},
constructor: TestA
};
function TestB(){
TestA.apply( this, arguments ); //Run parent constructor when instantiating a child
}
TestB.prototype = Object.create( TestA.prototype ); //Don't invoke the constructor when merely establishing inheritance
var test = new TestB();
test.count(); //0
var test2 = new TestB();
test2.count(); //0
据我所知,原型只有在读取属性时才会出现。通过实例而不是原型编辑特性时,实例将使其自己的特性具有相同的名称和编辑的值。原型值保持不变 在您的示例中,您携带了一个从外部看不到的私有变量。所以,它不能被“编辑”,它的值将通过继承类的所有实例传递 在中,这将使
num
成为公共的,以便在实例级别对其进行编辑和“修补”
var test, test2;
function TestA() {
this.num = 0; //public num
this.count = function() {
this.num++;
console.log(this.num);
}
}
function TestB() {} //instances of TestB don't have properties
TestB.prototype = new TestA();
test = new TestB();
test2 = new TestB();
//monitor the instances
console.log(test);
console.log(test2);
test.count(); //these create a num property at the instance level
test2.count(); //but the prototype num remains 0
test2.count();
test2.count(); //test will have 1 and test2 will have 3
计数操作前:
Object -> TypeA -> TypeB -> test
'-> num = 0 '->num = 0 (from TypeA)
'-> count() '->count() (from TypeA)
Object -> TypeA -> TypeB -> test2
'-> num = 0 '->num = 0 (from TypeA)
'-> count() '->count() (from TypeA)
计数操作后,prototypenum
保持为0,实例将具有num
:
Object -> TypeA -> TypeB -> test
'-> num = 0 '->num = 1 (on the instance)
'-> count() '->count() (from TypeA)
Object -> TypeA -> TypeB -> test2
'-> num = 0 '->num = 3 (on the instance)
'-> count() '->count() (from TypeA)
写入实例的继承属性时,将为该实例创建该属性的新副本 例如,假设您有:
var objB1 = new TypeB();
var objB2 = new TypeB();
其中,TypeB从TypeA继承val
属性
console.log(objB1.val); // reads the inherited value of property val
console.log(objB2.val); // also reads the inherited value of property val
但是当你写下这个属性的时候,比如:
objB1.val = 35; // objB1 now gets a new copy of the val property.
或
在上述两种情况下,当写入objB1.val
时,它不再引用继承的属性,而是创建属性val
的新副本,例如objB1
如果您想存储count,一种方法是共享它;为了方便起见,可以将其作为父类的构造函数的属性。因此,计数函数将变为:
function TestA(){
this.count = function(){
TestA.num++;
console.log(TestA.num);
}
};
TestA.num=0 不确定这是否有帮助:您不能将
num
作为TestA
对象的属性吗?不过,这会使它公开。@user1424240是的,它非常糟糕,这里语言的唯一语法帮助是new
:PYa;)我习惯了actionscript,在这里我可以声明“扩展”。嘿,还有一个问题,如果我想调用上一个super,如何声明重写方法?例如:TestB.prototype.count{//Call TestA count method here}@子类方法中的user1424240:TestA.prototype.count.call(this,arg1,arg2,arg3)
the.call
是所有函数的一种特殊方法,它将this
绑定作为第一个参数。当然,您可以手动设置TestB.prototype.parent=TestA
,然后this.parent.prototype.count.call(this)
function TestA(){
this.count = function(){
TestA.num++;
console.log(TestA.num);
}
};