5

継承と instanceof javascript キーワードの使用を含むバックボーン JS アプリケーションを構築しています。

私は次のコードを持っています:

app.Sport = Backbone.Model.extend
({
    defaults:
    {
        id: 0,
        title: 'Running'
    }
});

さらにコードで、次のように入力して新しい Sport をインスタンス化します。

var newSport = new app.Sport ();

この新しく作成されたインスタンスを問題なく操作できます。

しかし、 but があるため、 instanceof キーワードは、 my instance のタイプを要求するときに常に false を返します。

console.log ('is newSport a Sport instance ? ' + newSport instanceof app.Sport);

常に false を表示します。なんで ?

注:私の質問では継承について言及しませんでした。単純な形式の OOP (基本クラスの 1 つのインスタンス、およびその直後に型を要求する) でも機能しないためです。

私の最初の目的は、スポーツの種類に応じて特定のアクションをトリガーすることです (したがって、instanceof キーワードを使用します)。それはクールなものかもしれませんし、極端なものかもしれません:

app.CoolSport = app.Sport.extend ({ ... });
app.ExtremeSport = app.Sport.extend ({ ... });

編集:問題を分離しました。instanceof キーワードまたは宣言したモデルにリンクされていません。むしろ、バックボーン コレクションにデータを入力し、それに別の種類のスポーツをプッシュします。テストコードは次のとおりです:( Fiddle )

var app = {};


app.Sport = Backbone.Model.extend
({
    defaults:
    {
        id: 0,
        title: 'Running'
    }
});


app.CoolSport = app.Sport.extend
({
    defaults:
    {
        uselessAttr:'I am a Cool Sport !'
    }
});



app.SportList = Backbone.Collection.extend
({
    model: app.Sport

});


var coolSport1 = new app.CoolSport();

console.log ('is coolSport1 a Sport instance ? ' , coolSport1 instanceof app.Sport);

console.log ('is coolSport1 a CoolSport instance ? ' , coolSport1 instanceof app.CoolSport);

console.log ('is coolSport1 a CoolSport instance (wrong operand in console) ? ' + coolSport1 instanceof app.CoolSport);


var sportList = new app.SportList();
sportList.push (coolSport1.toJSON());


sportList.each ( function ( sport )
{
    if ( sport instanceof app.CoolSport )
    {
        console.log ( "sport is an instance of Cool Sport ! Yeah !" , sport instanceof app.CoolSport ) ;
    }                       
    else
    {
        console.log ( "Not a CoolSport instance..");
    }
});

そして、何を推測しますか?私の CoolSport インスタンスは... CoolSport インスタンスではありません。Backbone SportList コレクションの初期化が問題であると思われます。

何か案は ?

4

3 に答える 3

5

これをしないでください:

console.log ('is newSport a Sport instance ? ' + newSport instanceof app.Sport);

ちゃんとして:

console.log ('is newSport a Sport instance ? ' + (newSport instanceof app.Sport));

また

console.log ('is newSport a Sport instance ? ', newSport instanceof app.Sport);
于 2013-08-21T11:05:38.227 に答える
2

私は解決策を見つけました:-)

以下のコードにコメントしました:

var coolSport1 = new app.CoolSport();

// Of course it is
console.log ('is coolSport1 a Sport instance ? ' , coolSport1 instanceof app.Sport);

console.log ('is coolSport1 a CoolSport instance ? ' , coolSport1 instanceof app.CoolSport);


var sportList = new app.SportList();

// Here is the tricky part : we push the JSON representation of our CoolSport instance
sportList.push (coolSport1.toJSON());


// Backbone does not know anymore the subtype of our instance, as it has been JSON stringified juste before.
sportList.each ( function ( sport )
{
    if ( sport instanceof app.CoolSport )
    {
        console.log ( "sport is an instance of Cool Sport ! Yeah !" , sport instanceof app.CoolSport ) ;
    }                       
    else
    {
        console.log ( "Not a CoolSport instance..");
    }
});

バックボーンのドキュメントでは、この動作のメカニズムが提供されています。

var Library = Backbone.Collection.extend({

  model: function(attrs, options) {
    if (condition) {
      return new PublicDocument(attrs, options);
    } else {
      return new PrivateDocument(attrs, options);
    }
  }

});

正しいサブタイプ インスタンスをリストに追加するために、JSON 表現の処理方法をコレクションに指示します。したがって、コードを変更せずに CoolSport を追加するには、モデル関数を SportList コレクションに追加し、「uselessAttr」が含まれている場合は新しい CoolSport を返す必要があります (私の質問のコードを参照してください)。

私は別の方法を取り、コレクションの add() メソッドを介して CoolSport インスタンスを直接渡し、そのサブタイプを維持しました。

助けてくれてありがとう、そして私の答えが他の人に役立つことを願っています:-)

于 2013-08-21T14:31:54.653 に答える
1

コレクション内のモデルを「app.Sport」として定義しています

したがって、coolSport1.toJSON() をプッシュすると、app.Sport モデルを使用して初期化されます。

これが、CoolSport インスタンスではなく、Sport インスタンスである理由です。

于 2013-08-21T14:36:17.667 に答える