2011-06-14 20 views
1

I also have this running example on jsfiddle
サンプル:私は私が働いている小規模なプロジェクトを持っていると私は、継承の種類を実装したかった本当に簡単なJavaScriptを「継承」(質問の例)

function Animal(o) { 
    o.class = Animal; 
    o.name = o.name ? o.name : "Animal"; // Defaults 
    o.age = o.age ? o.age : 0; // Defaults 
    o.weight = o.weight ? o.weight : 0; // Defaults 
    o.say = o.say ? o.say : "?"; 

    Animal.isOnEarth = true; // "static variable" 

    return o; 
} 
function Cow(o) { 
    o.class = Cow;   
    o.name = o.name ? o.name : "Cow"; // Defaults 
    o.milk = o.milk ? o.milk : 0; // Defaults 
    o.say = o.say ? o.say : "MOOO"; 

    return Animal(o); //Inheritence 
} 
function Dog(o) { 
    o.class = Dog;   
    o.isCrazyLab = o.isCrazyLab ? o.isCrazyLab : false; 
    o.say = o.say ? o.say : "WOOF"; 

    return Animal(o) //Inheritence; 
} 

function Labradore(o) { 
    o.class = Labradore;   
    o.isCrazyLab = o.isCrazyLab ? o.isCrazyLab : true; 
    o.say = o.say ? o.say : "YARRWL"; 

    return Dog(o) //Inheritence; 
} 

var cow = Cow({}); 
var bessy = Cow({name:"bessy",milk:25}); 
var spot = Dog({name:"spot"}); 
var hugo = Labradore({name:"hugo"}); 

document.write("True or false, all these animals live on earth " + Animal.isOnEarth + " A cow says " + cow.say + "... bessy's name is " + bessy.name + " a " + spot.name + " says " + spot.say + " " + hugo.name + " says " + hugo.say); 

。私はいくつかのサンプルをオンラインで見ましたが、JavaScriptの基本的な動作を修正するすべてのリグマームルルを通過することが重要なのはどういうことなのかよくわかりません。私にとっては、javascriptのクラス概念を拡張して、別の言語のように「感じる」ように感じるだけで、いくつかの行を節約できますが、多くのコア機能を追加するようには見えません。しかし、私は教育されて満足しています:)

いくつかの質問
この方法で動作するライブラリはありますか?
これを行う際の長所と短所はありますか?
これをしないと根本的な理由はありますか?
一般的な考えですか?

答えて

4

は、その用語は、必ずしもここで問題はありません:-)

私が見る主な欠点は以下の通りです。

  • instanceofはしませんwork
  • JavaScriptは実装間でリソースを共有するためのメカニズムを失います(プロトタイプチェーン)。
  • 言語で定義されている他のオブジェクトとは驚きです。オブジェクトをコンストラクタに渡す必要が常にあるとは思っていませんが、newを使用することを期待しています。
  • "super"のバージョンの関数を呼び出す明確な方法はありません。

オフトピック:ノートのカップル:

  • classのJavaScriptの予約語です。 forまたはifを識別子として使用しないのと同じように、識別子として使用しないでください。
  • あなたは例えば、curiously-powerful || operatorを使用してビットを簡素化することができます。:

    o.name = o.name || "Cow"; // Defaults 
    
+0

ああ、非常に良い、このフィードバックありがとうございます – samwise

+1

@サムワイル:いいえ心配。興味があれば、私のブログで相続に関するかなり徹底的な記事を書いています:http://blog.niftysnippets.org/2009/09/simple-efficient-supercalls-in.html私は再訪することを意味していますそれはJavaScriptの標準的なプロトタイプの継承に文法的な砂糖が詰まっているだけなので、用語を「クラス」の概念から外すように変更しています。JavaScriptで「クラス」用語を使用することは非公式に行う必要があります。本当に適用されます。 –

2

次のように私自身の問題がある:

document.write(hugo.class == Animal) // true 
document.write(hugo.class == Labradore) // false 
+0

ほら!よかった!私は同じチェックをクラス – samwise

1

私は最近、ジョンResig氏の "Simple JavaScript Inheritance" スクリプトを使用して開始しました。 (ジョンResig氏は、jQueryの担当の男がある:。天才は、私は強くあなたがまだの場合は彼のポストを読ん勧めしたい

この構文は、私にはとてもクリーンでエラーが発生しやすい少なくなります。

。それは基本的にコピーしています、本当に継承ではありません
var Animal = Class.extend({ 
    name : "Animal", 
    age : 0, 
    weight : 0, 
    say : "?" 
}); 
Animal.isOnEarth = true; // "static variable" 

var Cow = Animal.extend({ 
    name: "Cow", 
    milk: 0, 
    say: "MOOO" 
}); 
+0

に追加することができたと思う私はそれを見ていた、この部分は私が問題を抱えていた唯一のものだった:(新しいプロトタイプにプロパティをコピー... beginループ)...なぜか分かりません。大したことではないかもしれませんが、各プロパティを繰り返しチェックし、手動でチェックするというコンセプトは、余計に感じられます。 – samwise

+0

@サムワイク:ジョンのスクリプトを「フレームワーク」と考えてください。これは、継承のきめの細かい部分を処理します。つまり、手動で行う必要はありません。 – StriplingWarrior

+1

Resigのスクリプトはそれほど悪くはありませんが、悲しいことに、関数の逆コンパイルがスーパーコールのサポートに依存しています。これは少し隠されていますが、関数のサブクラスのオーバーライドは 'Function#toString'(暗黙的に、' RegExp#exec'に渡すことで)によって解除されます。問題は、 'Function#toString'は決して標準化されておらず、一部のモバイルブラウザでは実際には機能しません。それは、 "_super"がメソッド内のどこにでも(たとえ文字列の中で、変数名としてであれ、何でも)出現し、スーパーコールマジックがそれを囲むことを望んでいるとうれしく思います。 –