0

プロトタイプの継承を使用する方法を理解しようとしています。これが私が以下に持っているコードです。これは、Stoyan Stefanovによる「オブジェクト指向Javascript」という本に基づいていますが、いくつかの変更が加えられています。

基本的に私はAthleteオブジェクトを拡張するオブジェクトを持っていPersonます。3つのオブジェクトを作成しました。ボブは、PersonビリージーンとスティーブはAthletesです。ボブ、ビリージーン、スティーブをその特定の順序で追加しました。ボブ、ビリージーン、スティーブの3つのオブジェクトすべてで、オブジェクトに対して、関数say()run()関数を呼び出しました。getSpeed()jump()Athlete

以下のコードがあります。

<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のプロパティが2回ポップアップします。つまり、SteveがBillyJeanを置き換えました。以下に示す出力。

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

ビリー・ジーンとスティーブを分離して、スティーブの詳細ではなく両方の詳細を2回取得する方法があるかどうか、疑問に思っていました。

それが不可能な場合、この問題を解決するために代わりにどのような代替手段を使用できますか?どんな解決策や助けも大きな助けになるでしょう。

4

2 に答える 2

1

この特定の行は、Athlete.initializeの例では問題があります。

//uber is the parent
this.uber.initialise(name);

この呼び出しでは、アスリート間で共有される、で表されるオブジェクトinitialize を呼び出します。uberこれを次のように変更します。

this.uber.initialize.call(this, name);

追加のパラメータを通過する実際のオブジェクト(これ)uberinitialize から呼び出す。

于 2011-10-20T07:58:06.153 に答える
0

これがあなたの問題です。「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」を「新しい」Athletes(Athletesオブジェクトのクローンではない)と見なしているため、「steve = new Athlete('Steve'); '

私の2セント、それがお役に立てば幸いです。

于 2011-10-20T08:10:39.630 に答える