原型继承对象的多个实例
Prototypal Inheritance Multiple Instances of Objects
我正在尝试掌握使用原型继承的方法。下面是我的代码。它基于Stoyan Stefanov的《面向对象的Javascript》一书,只做了一些修改。
基本上我有一个扩展了Person
对象的Athlete
对象。我创建了3个对象。鲍勃是Person
,而比利·简和史蒂夫是Athletes
。我按这个顺序加上了鲍勃、比利·简和史蒂夫。我调用了say()
和run()
函数,以及getSpeed()
和jump()
,对于Athlete
对象,在所有3个对象中以这个特定的顺序:Bob, Billy Jean和Steve。
代码如下:
<script type="text/javascript">
function clone(o) {
var n;
function F(){};
F.prototype = o;
n = new F();
return n;
}
/* Uber is equivalent to the extends method */
function uber(parent, child) {
var n = clone(parent);
n.uber = parent;
for (var i in child) {
n[i] = child[i];
}
return n;
}
var Person = {
initialise: function(name)
{
this.name = name;
},
say: function()
{
console.log('My name is ' + this.name + '. I am a person');
},
run: function(){
console.log('I have run 5km');
},
jump: function() {
console.log('I have jumped for joy!');
}
};
var Athlete = {
initialise: function(name,speed) {
this.speed = speed;
//uber is the parent
this.uber.initialise(name);
},
say: function() { console.log('My name is ' + this.name + '. I am an athlete');},
run: function() { console.log('I have run 20km'); this.jump()},
getSpeed: function() {console.log('My Speed is: ' + this.speed + 'km Hour');}
}
var Athlete = uber(Person, Athlete);
console.log("Hello, Starting Test...");
var bob = clone(Person);
bob.initialise('Bob');
bob.say();
bob.run();
console.log("Adding Billy Jean...");
var billyJean = clone(Athlete);
billyJean.initialise('Billy Jean', 15);
console.log("Adding Steve...");
var steve = clone(Athlete);
steve.initialise('Steve', 25);
console.log("Asking Billy Jean...");
billyJean.say();
billyJean.run();
billyJean.getSpeed();
console.log("Asking Steve...");
steve.say();
steve.run();
steve.getSpeed();
</script>
然而,当我运行代码时,虽然我先为Billy Jean调用了函数,但Steve的属性弹出了两次,这意味着Steve取代了Billy Jean。输出如下所示。
Hello, Starting Test...
My name is Bob. I am a person
I have run 5km
Adding Billy Jean...
Adding Steve...
Asking Billy Jean...
My name is Steve. I am an athlete
I have run 20km
I have jumped for joy!
My Speed is: 15km Hour
Asking Steve Tran...
My name is Steve. I am an athlete
I have run 20km
I have jumped for joy!
My Speed is: 25km Hour
我只是想知道是否有一种方法可以将Billy Jean和Steve分开,这样我就可以同时获得他们的详细信息,而不是两次获得Steve的详细信息。
如果这是不可能的,那么我可以用什么替代方法来解决这个问题?任何解决方案或帮助将是一个很大的帮助。
在您的示例中,这一行有问题:
//uber is the parent
this.uber.initialise(name);
在这个调用中,你调用initialize
上的对象,该对象由uber
表示,在你的运动员之间共享。将其更改为:
this.uber.initialize.call(this, name);
调用initialize
从 uber 在你的实际对象(this)传递额外的参数。
这是你的问题。"这。"uber"引用的是steve和billyJean共享的对象。对象是通过引用传递的,这就是为什么会发生这种情况。尝试替换
this.uber.initialise(name);
this.uber.initialise.call(this, name);
(如果你不知道,'call'和'apply'使'methods'在不同的范围内运行)。我对你的经历没有任何真实的背景,所以希望接下来的漫谈不会冒犯你。但是,我有一些想法。我很少看到javascript这样做。大多数时候,它更像是……
var bob = new Person();
bob.initialise('Bob');
bob.say();
bob.run();
为什么是"克隆"?你想要一个纯粹的方法吗?如果是这样,"克隆"也好不到哪里去——你还在喊"新",还在耍点小把戏。一个纯粹的方法会更多的是…(请原谅jQuery…懒惰)
Object.prototype.clone = function () {
return $.extend(true, {}, this);
};
Object.prototype.improve = function (extras) {
var spawn = $.extend(true, {}, this, extras);
spawn.uber = this;
return spawn;
};
var Person = {
initialise: function(name) {
this.name = name;
},
say: function() {
console.log('My name is ' + this.name + '. I am a person');
},
run: function(){
console.log('I have run 5km');
},
jump: function() {
console.log('I have jumped for joy!');
}
};
var Athlete = Person.improve({
initialise: function(name,speed) {
this.speed = speed;
//uber is the parent
this.uber.initialise.call(this, name);
},
say: function() { console.log('My name is ' + this.name + '. I am an athlete');},
run: function() { console.log('I have run 20km'); this.jump()},
getSpeed: function() {console.log('My Speed is: ' + this.speed + 'km Hour');}
});
var bob = Person.clone();
bob.initialise('Bob');
bob.say();
bob.run();
console.log("Adding Billy Jean...");
var billyJean = Athlete.clone();
billyJean.initialise('Billy Jean', 15);
console.log("Adding Steve...");
var steve = Athlete.clone();
steve.initialise('Steve', 25);
console.log("Asking Billy Jean...");
billyJean.say();
billyJean.run();
billyJean.getSpeed();
console.log("Asking Steve...");
steve.say();
steve.run();
steve.getSpeed();
这同样有效。请注意,我在这里仍然使用'call' -这是因为原始的是通过引用传递的。你可以撤销……让它通过克隆…但实际上,这是在浪费内存,而且90%的时间都是循环的。
所以,这是我最好的"纯粹"方法!我个人不喜欢这种方式,因为我认为'steve'和'billyJean'是'new' Athletes -而不是' Athletes '对象的克隆-所以我更倾向于使用一个模式,让我这样做'steve = new Athlete(' steve');'
我的两分意见,希望能有所帮助。
- 为什么函数对象的实例没有继承函数原型属性
- JavaScript继承:为什么从实例复制
- 使用Object.create作为原型的原型继承将[Object]作为实例的原型
- AngularJS:多个工厂实例任何原型继承
- 基于实例的 JavaScript 继承
- 从继承的实例创建 JavaScript 基类对象
- 通过构造函数属性和运算符实例设置继承
- 如何让每个实例继承其自己的成员实例
- 使用函数继承时相当于“实例”
- 在Javascript中使用寄生继承,是否可以实现内省实例方法
- 检查原型的继承,而不是实例
- 通过伪经典实例化(JavaScript)掌握原型继承
- 具有继承同一父级的类的sibings实例的主干继承模式
- 使用Object.keys获取用于创建构造函数实例的属性,然后打印继承的属性
- 在JavaScript中使用原型继承时,如何避免创建基类的实例
- 为什么实例没有't在没有prototype关键字的情况下继承添加到构造函数的属性
- 如何在JavaScript中进行继承,而不会在子类的所有实例之间共享父类的相同实例?
- Javascript继承静态和实例方法/属性
- javascript继承:实例vs原型
- 从javascript中的一个实例继承