0

2つの関数が相互に継承する方法を次のように定義します。

Function.prototype.inherit = function(parent){

function proto() {}
proto.prototype = parent.prototype;

this.prototype = new proto();
this.prototype.constructor = this;
this.prototype.parent = parent; 

}

次に、JavaのinstanceOfまたはPHPのinstanceofのように動作するisInstance関数を定義する必要があります。本質的に、isInstanceを使用して、変数が親関数から継承する関数のインスタンス化されたオブジェクトであるかどうかを判断できます。

これは私が書いたものです:

Function.prototype.isInstance = function(func){
if(this == func){
    return true;
} else{
    if (this.prototype.parent == undefined || this.prototype.parent == null) {
        return false;   
    } else {
        return this.prototype.parent.isInstance(func);          
    }
}

}

これは、2つの関数を比較する場合は正常に機能しますが、インスタンス化された変数を比較する場合は機能しません。

Object2.inherit(Object1);

Object2.isInstance(Object1); //returns true

var obj2 = new Object2();

obj2.isInstance(Object1);// obj2.isInstance is not a function

上記の最後のケースは、私が働きたいものです。関数だけでなく、インスタンスにisInstanceを追加するにはどうすればよいですか?そして、そこにあるすべてのjavascriptの達人にとって、私のコード(おそらくinheritメソッド)に何か改善はありますか?

ありがとう。

4

3 に答える 3

6

次に、JavaのinstanceOfまたはPHPのinstanceofのように動作するisInstance関数を定義する必要があります。

JavaScript自体の何が問題になっていますinstanceofか?

あなたの継承機能を考えると、

function Shape() {};
function Square() {};
Square.inherit(Shape);
alert(new Square() instanceof Shape); // true

instanceof指定されたコンストラクターのprototypeプロパティがインスタンスのプロトタイプチェーンにあるかどうかを確認することで機能します。だから例えば。

function A() {};
function B() {};
var b= new B();
A.prototype= B.prototype;
alert(b instanceof A); // true

これが、 ;を使用して作成されていなくinstanceof Shapeても機能する理由です。代わりに、によって作成されましたが、両方が同じプロパティを共有しているため、JavaScriptは違いを区別できません。Square.prototypenew Shapenew proto()protoShapeprototype

通常、プロトタイプチェーンは表示されませんが(FirefoxとWebKitは__proto__プロパティを介して利用可能にしますが)、JSで継承が実際に処理される方法です。new表示されるFunction.prototypeプロパティは、 -timeでプロトタイプチェーンの初期状態を設定するためにのみ使用されます。

関数だけでなく、インスタンスにisInstanceを追加するにはどうすればよいですか?

Object.prototype.isInstance(c)= function() {
    return this instanceof c;
}

しかし、これが本当にあなたに多くをもたらすかどうかはわかりません!また、Objectへのプロトタイピングは、文字通りすべてのオブジェクトに影響を及ぼし、ルックアップマッピングにObjectを使用する他のスクリプトを混乱させる可能性があるため、趣味が悪いと見なされることがよくあります。

私のコードに何か改善はありますか(おそらくinheritメソッド)?

私はあなたのinheritメソッドが好きです、それはオブジェクトシステムを作るより軽量でJavaScriptのような方法の1つです。

他の便利な目的でそれらが必要でない限り、プロパティをinstanceof失う可能性があります。ただし、コンストラクター関数をオンにして(つまり、基本クラスを知っているサブクラスのようなものです)、別の関数を呼び出します(Firefoxには既にプロパティが呼び出されていますが、思ったとおりに動作せず、一般的に最適です)回避)。parentconstructorparentconstructorconstructor

私が見る唯一の欠点は、コンストラクター関数を継承できないことです。したがって、新しいサブクラスを作成するたびに、サブクラスのコンストラクターが何もしない場合でも、基本コンストラクターを呼び出すコンストラクターを作成する必要があります。

function Square() {
    Shape.apply(this, arguments);
}
Square.inherit(Shape);
于 2009-10-03T17:32:09.030 に答える
4

なぜあなたはこれをする必要がありますか?JavaScriptには、厳密なクラス階層の概念がありません。理由は、実際には実行できないからです。ほとんどの場合に機能するソリューションを見つけることができるかもしれませんが、すべてのエッジケースをカバーできるかどうかはわかりません。さらに、JavaScriptにはインターフェースの概念がないため、明示的な継承をテストすると結合度が高くなり、SOLIDの原則に違反しているように見えます。

この問題に取り組むためのはるかに優れた(そしてより慣用的な)方法は、ダックタイピングを使用することです。必要なメソッドの存在をテストしてから呼び出すだけです。必要に応じて例外をキャッチする準備をしてください(とにかく実行する必要があります)。

于 2009-10-03T16:18:48.397 に答える
1

良い設計の議論を少し脇に置いて問題に焦点を合わせるために、問題はあなたがのプロトタイプのisInstance()メソッドになるように設定することです。Functionつまり、Functionsであるオブジェクトにはそれがありますが、そうでないオブジェクト(例のようObject1Object2)にはありません。

メソッドとして実装するのではなく、静的関数にすることをお勧めします。

function isInstance(object, ofClass) {
  // Same logic as you have, except use 
  // object.prototype instead of this.prototype
}

その後、次のように呼び出すことができます

isInstance(obj2, Object2);
于 2009-10-03T16:52:55.333 に答える