2009-08-13 14 views
2

Javascriptで継承を理解しようとしていますが、このコード(Firebugでテスト済み)は期待通りの動作をしません。私はそれについて何を理解していないのですか?私は期待してい何コンストラクタの継承。私はここにいないのですか?

var A = function(v){ 
    this.v = v || 'foo'; 
} 

A.prototype.shout = function(){ alert(this.v); } 

var B = function(){}; 

B.prototype = new A; 

var test = new B('bar') 
test.shout() // returns 'foo' 

は私がtestプロパティthis.vを割り当てるときには、「バー」に設定されていることです。私の知る限り、JSプロトタイプの継承設定BのプロトタイプAは、Bのすべてが上書きされることを意味します。私はそれがコンストラクタが上書きされることを期待し、new B('bar')を呼び出すと、Aのコンストラクタがパラメータ "bar"で実行されます。

私の理解が間違っている場合は、誰かが私を修正してください。また、私が何をしているよ何の解決策を見つけるために良いでしょう:私は作成していJSオブジェクトは、標準的なOOPに似た遺伝パターンに従うように...

// constructors from above 
B.prototype.yell = function(){ alert('hello world'); } 
var test1 = new B('bar'), test2 = new B('spam'), test3 = new B('eggs'); 

を、したがって、Bを継承しますAのコンストラクタとメソッド。

編集:

のコメントを読んだ後、私はより良い質問は1 s「をAでのコンストラクタ」はBを上書きする方法を尋ねることであろうと考えていますか?

+2

期待どおりに動作しないのはなぜですか?あなたは何を期待していますか? –

答えて

2

次はコンストラクタです。もしBコンストラクタで新しいA.

var A = function(v){ 
    this.v = v || 'foo'; 
} 

呼び出すときには、関数(){}で実行されます。だから、あなたはあなたがこのパターンに従ってくださいしようとしている結果を達成するためにthis.v

を設定されていません。あなたが

var B = function(){}; 

を設定するときは、パラメータなしのコンストラクタBを

var A = function(v){ 
    this.v = v || 'foo'; 
} 

A.prototype.shout = function(){ alert(this.v); } 

var B = function(v){ 
    B.prototype.constructor.call(this,v); // here you call A constructor 
}; 

B.prototype = new A; 


var test = new B('bar') 
test.shout() // returns 'bar 
+0

私が理解している限り、 'B.prototype'を設定すると' A'から* everything *がコピーされましたか?それは間違っていますか? –

+0

はい。しかし、新しいClass()を呼び出すと、コンストラクタを呼び出すだけです。そしてBの場合、コンストラクタはfunction(){}は何もしません。 –

1

作成するとときあなたdo

B.prototype = new A; 

Aパラメータを持たないコンストラクタ(this.v = 'foo'を引き起こして)Bのプロトタイプが、vshoutを指すようにします。ただし、コンストラクタとしてBは変更されていません。これは、例えば、「B」の定義にいくつかのパラメータを追加することによって見ることができる。

var B = function(x){this.v += x}; 

が「foobarに」を生成すべきです。

補遺: 私は、コンストラクタは、いくつかのサードパーティの機能との両方のコンストラクタを作成し、& B.例の両方に割り当てることが実際にある「コピー」と考えることができます最も近い道:

var objmaker = function(defaultval) { 
    return function(v) { this.v = v || defaultval; }; 
} 

var A = objmaker('foo'); 
A.prototype.shout = function(){ alert(this.v); } 

var B = objmaker('bar'); 
B.prototype = A.prototype; // B can now shout() 

var testA1 = new A('A'); 
testA1.shout(); // returns 'A' 
var testA2 = new A(); 
testA2.shout(); // returns default 'foo' 

var testB1 = new B('B'); 
testB1.shout(); // returns 'B' 
var testB2 = new B(); 
testB2.shout(); // returns default 'bar' 

異なるデフォルト値で見ることができるように、実際にコピーしているわけではありませんが、2つの定義を確実に同期させる1つの方法です。

+0

'B'のコンストラクタを' A'に置き換える方法はありますか? –

+0

Bはコンストラクタです。 Bはクラスではなく、コンストラクタ関数です。 Javascriptにはクラスがありません。 – Breton

+0

授業について誰が言ったのですか? –

0

私はあなたが「VaRのB」の新しい機能ではなく、それは新しいA '作りをするとき、あなたはあなたのように 『A』を作っ 『コンストラクタ』を一掃。考える

var test2 = new A('baz'); 
test2.shout(); //returns baz 

をお試しください テストのインスタンスvを 'foo'に設定するためにオリジナルがまだ呼び出されているかどうかはわかりません。

+0

私はそれが解決策だとは思いません。例えば、 'A'は' B'と 'C'によって継承される共通のメソッドを含んでいます。 'B'は' C'と同様に 'A'が持たない追加のメソッドを定義します。ですから、 'B'のインスタンスを作成する必要がありますが、' A'のコンストラクタを渡す必要があります。 –

-2

javascriptを他の言語のように動作させようとするのではなく、新しいものを学んで使用して、javascriptのように動作させることができますか? http://javascript.crockford.com/prototypal.html

+0

私は* javascriptのように使用しようとしています*。私はある言語のイディオムを理解しており、そのイディオムを別の言語に複製する際に助けを求めています。 –

+0

しかし、それはjavascriptのようではありません。他の言語と同じです。イディオムはjavascriptで意味をなさない。リンクを読むと分かります。それはあなたが正確にやりたいことのための指示と別のページへのリンクを持っています。 – Breton

+0

私は、あなたはjavascriptで "Goto"をどうやってやっているのか聞いているかもしれませんが、javascriptにGOTOコマンドがないことを指摘するのは無理でしょうか? – Breton

1

代わりAの新しいインスタンスにプロトタイプを設定するので、BprototypeさんがprototypeデリゲートAまで「作る:

はこれを見て持っています。 Crockfordはこのビッツと呼ばれ、Dojoの dojo.delegateとして実装されています。それはこのようになります簡単な関数です:

function delegate(o){ 
    F = function(){} 
    F.prototype = o; 
    return new F; 
} 

そして、あなたはプロトタイプの間に、このリンクを作成するためにそれを使用することができます。これにより

var B = function(){} 
B.prototype = delegate(A.prototype); 

と呼ばれることは決してありませんAコンストラクタ、およびv値決して設定されません。これは継承をプロトタイプのみに限定し、プロトタイププラスコンストラクタには制限しません。

+0

プロトタイプチェーンを設定するための一時的なF()の使用を忘れてしまった。説明ありがとう。 1つの質問のみ、B.prototypeを設定する必要はありません。BがBのインスタンスであることを確認するためのコンストラクタ= B? – asumaran