原型继承对象的多个实例
我正在尝试掌握使用原型继承的方法。这是我下面的代码。它基于 Stoyan Stefanov 的《面向对象的 Javascript》一书,仅做了一些修改。
基本上我有一个 Athlete
对象,它扩展了 Person
对象。我创建了 3 个对象。鲍勃是一个人
,而比利·吉恩和史蒂夫是运动员
。我按照特定的顺序添加了鲍勃、比利·吉恩和史蒂夫。我调用了 say()
和 run()
函数以及 getSpeed()
和 jump()
,对于 < code>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
我只是想知道是否有办法将比利·吉恩和史蒂夫分开,以便我两次获得他们的详细信息而不是史蒂夫的详细信息?
如果不可能,那么我可以使用什么替代方案来解决这个问题?任何解决方案或帮助都会有很大的帮助。
I'm trying to get the grips of using prototypal inheritance. Here is the code I have below. It is based on the book "Object -Oriented Javascript" by Stoyan Stefanov, with just a few modifications.
Basically I have an Athlete
object that extends a Person
object. I have created 3 objects. Bob is a Person
, while Billy Jean and Steve are Athletes
. I added Bob, Billy Jean and Steve in that particular order. I invoked say()
and run()
functions and getSpeed()
and jump()
, for the Athlete
objects, in all 3 objects in this particular order: Bob, Billy Jean and Steve.
Here is the code below.
<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>
However, when I run the code, although I invoke the functions for Billy Jean first, Steve's properties pop up twice, meaning Steve replaced Billy Jean. Output shown below.
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
I was just wondering if there is a way to separate Billy Jean and Steve So that I get both their details instead of Steve's details twice?
If it's impossible then what alternative can I use instead to solve this problem? Any solution or help would be a great help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此特定行在 Athlete.initialize 的示例中存在问题:
通过此调用,您可以在
uber
表示的对象上调用initialize
,该对象是共享的在你的运动员中。将此更改为:从您的实际对象(this)上调用初始化,传递附加参数。
This particular line is problematic in your example in Athlete.initialize:
With this call, you call
initialize
on object represented byuber
, which is shared among your athlets. Change this to:to call
initialize
from uber on your actual object (this) passing additional paremeters.这是你的问题。 “this.uber”引用了 steve 和 billyJean 之间共享的对象。对象是通过引用传递的,所以这就是发生这种情况的原因。尝试替换
为
(如果您不知道,“调用”和“应用”使“方法”在不同的范围内运行)。我对你的经历没有任何真实的背景,所以希望接下来的闲聊不会侮辱......但是,有一些想法。我很少看到 JavaScript 是这样做的。大多数时候,它更像是……
为什么是“克隆”?您想要一种纯粹的方法吗?如果是这样,“克隆”也好不了多少——你仍然称其为“新”并施展一点魔法。纯粹的方法会更多..(请原谅 jQuery.. 的懒惰)
这也同样有效。请注意,我在这里仍然使用“调用” - 这是因为原始数据是通过引用传递的。你可以撤消这个操作.. 让它通过克隆.. 但实际上,90% 的时间这都是内存和循环的浪费。
所以,这就是我最好的“纯粹”方法!我个人不喜欢这种方式,因为我将“steve”和“billyJean”视为“新”运动员 - 而不是运动员对象的克隆 - 所以我更倾向于使用一种模式,让我可以执行“steve =”新运动员('史蒂夫');'
我的两分钱,希望有帮助。
Here's your issue. "this.uber" is referencing an object that is shared between steve and billyJean. Objects are passed around by reference, so that's why this is happening. Try replacing
with
(In case you aren't aware, 'call' and 'apply' make 'methods' run in different scopes). I don't have any real background on your experience, so hopefully this next ramble isn't insulting.. but, a few thoughts. I've rarely seen javascript done like this. Most of the time it has been something more along the lines of...
Why the 'clone'? Did you want a purist approach? If so, the 'clone' isn't any better - you're still calling 'new' and doing a little magic. A purist approach would be more of.. (pardon the jQuery.. being lazy)
This works just as well. Note that I'm still using 'call' here - it's because the original is passed by reference. You could undo that.. make it pass a clone.. but really, it's a waste of memory and cycles 90% of the time.
So, there's my best 'purist' approach! I personally don't like this way, as I see 'steve' and 'billyJean' as 'new' Athletes - not clones of an Athletes object - so I'd be more inclined to use a pattern that lets me do 'steve = new Athlete('Steve');'
My two cents, hope it helps.