2012-01-04 19 views
6

Javascriptの関数にプロトタイプ継承を適用​​しようとしています。それはすべてかなり平凡で、さらにWikipedia's javascript lemmaで説明されています。 Employee.prototype = new Person();javascriptプロトタイプの継承とオブジェクトのプロパティ

function Person() { 
    this.age = 0; 
    this.location = { 
     x: 0, 
     y: 0, 
     absolute: false 
    }; 
}; 

function Employee() {}; 

Employee.prototype = new Person(); 
Employee.prototype.celebrate = function() { 
    this.age++; 
} 

var pete = new Employee(); 
pete.age = 5; 
pete.celebrate(); 
var bob = new Employee(); 
bob.celebrate(); 
console.log("bob is " + bob.age + " pete is " + pete.age); 

、すべての人のプロパティと(プロトタイプ化)メソッドを継承の基本である従業員に継承されています。それは私の性質が簡単なjavascriptの種類である場合に動作します。

これは期待通りに動作します:直感的なコントラあるtrueを、(:私はピートの場所をいじるために始めている今、bob is 1 pete is 6

pete.celebrate(); 
pete.location.absolute=true; 

表示bob.location.absoluteを示し(祝った後)私はボブの場所に触れなかったので、それはPersonで宣言された初期値を持つと期待しています。

これは私の最初の理解では間違っていたはずです。私はおそらく最初のPersonから位置オブジェクトをクローン化するべきであることを認識していますが、これを行う場所や方法はわかりません。 そして、おそらく継承のためのより良いテクニックがあれば?

答えて

3

新しいEmployeeをインスタンス化すると、Personのすべてのプロパティがコピーされます。これは浅いコピーなので、peteとbobは同じ場所オブジェクトを共有します。あなたの問題については、非常に良い解決策はありません。

function Employee() { Person.apply(this); }; 

これは、このオブジェクトのコンテキストでPersonコンストラクタを呼び出します。

MDCはこの詳細があります:継承する場合https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply

3

Personコンストラクタを実行しないでください、それはPerson.prototypeではないので、Employee.locationを持っていない はずですが。

function createObject(fn){ 
    function f(){} 
    f.prototype = fn.prototype; 
    return new f; 
} 

その後:

Employee.prototype = createObject(Person); 

これは、副作用(コンストラクタを実行)することなく、適切に継承します。

あなたは一人っ子コンストラクタで親のコンストラクタを実行します:

function Employee() { 
Person.apply(this, arguments); 
} 
+0

新しいPerson()ではなくcreateObject(Person)を使用することのメリットは何ですか?プロトタイプ間接参照の1つのレイヤーしか追加しません。 – Kosta

+0

@Kostaは、継承時にコンストラクタを実行することによる副作用を回避します。コンストラクターには初期化コードがありますが、何もインスタンス化していないときには実行したくない場合があります。 'Person.prototype'と' f.prototype'の両方が同じオブジェクトを指しているので、 'new Employee'は' instanceof Person'です。 – Esailija

+0

しかし、あなたはまだcreateObject()(一度)でコンストラクタを実行しています。また、コンストラクタをEmployee()(各インスタンシエーションごとに)で実行しています。 createObject()が役に立つ例を挙げてください。 – Kosta

0

私は同様の問題に遭遇しました。私は内部オブジェクトのための別のコンストラクタを使用して終了しました。

function engine(cc, fuel) { 
     this.cc = cc; 
     this.fuel = fuel 
} 

function car(type, model, cc, fuel) { 
     this.type = type; 
     this.model = model; 
     this.engine = new engine(cc, fuel); 
} 


var mycar = new car("sedan", "toyota corolla", 1500, "gas"); 
console.log(mycar.type); 
//sedan 
console.log(mycar.engine.cc); 
//1500 

私は「エンジン」や「車のコンストラクタのプロトタイプ上の任意のメソッドを持っていた場合、彼らはまだ使用可能になります。しかし、私はOOPの意味で "engine"クラスから "car"クラスを派生していません。私はする必要はなかった。 「エンジン」は「車」の構成要素として使用されます。

一方、継承のために、ECMAScript 5に組み込まれている新しいメソッド(Object.create、Object.definePropertiesなどを使用することを意味します)を使用することをお勧めします。これらはIE9でもサポートされています。その前に、私はKostaが提案した同じ 'apply()'メソッドを使用しました。

関連する問題