2013-08-21 11 views
6

Buduję aplikację szkieletową JS, która obejmuje dziedziczenie i użycie instancji javascript.Dlaczego słowo kluczowe instanceof nie działa z modelami Backbone js?

Mam następujący kod:

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

Ponadto w kodzie, I instancji nowy sport wpisując:

var newSport = new app.Sport(); 

mogę manipulować tej nowo utworzonej instancji bez problemów.

Ale, ponieważ nie jest to jednak słowo kluczowe instanceof zawsze return false gdy prosi o rodzaju mojego przykład:

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

zawsze wyświetla fałszywe. Czemu ?

Uwaga: W moim pytaniu nie wspomniałem o dziedziczeniu, ponieważ nie działa ono nawet z prostą formą OOP (jedna instancja klasy bazowej i pytanie o typ zaraz po).

Moim początkowym celem jest wywołanie określonych działań w zależności od rodzaju sportu (czyli użycie słowa kluczowego instanceof); to może być fajny, lub ekstremalnym jeden:

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

EDIT: I izolowane problem. Nie jest on powiązany ze słowem kluczowym instanceof lub z deklarowanym przeze mnie Modelem. Zamiast tego, zapełniam kolekcję kręgosłupa i popycham do niej różne rodzaje sportów. Oto kod testowy: (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.."); 
    } 
}); 

I zgadnij co? moja instancja CoolSport ... nie jest instancją CoolSport. Podejrzewam, że problemem była inicjatywa kolekcji Backbone SportList.

Wszelkie pomysły?

+0

Wydaje się pracować http://jsfiddle.net/nikoshr/dX7Nz/ – nikoshr

+1

I skrzypce, aby odtworzyć twój problem, ale moje testy pokazują, że to powinno działać zgodnie z oczekiwaniami. Którą wersję szkieletu/podkreślenia masz na sobie? (skrzypce: http://jsfiddle.net/HHS8u/) – jakee

+1

spróbuj zapisać console.log ("is newSport a Sport instance?", (newSport instanceof app.Sport)); - pojawi się instancja ''to newSport a Sport instancja? + newSport' - będzie to ciąg – Sergey

Odpowiedz

2

znalazłem rozwiązanie :-)

ja skomentował kod poniżej:

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.."); 
    } 
}); 

dokumentacja Backbone zapewnia mechanizm dla tego zachowania:

var Library = Backbone.Collection.extend({ 

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

}); 

Mówi kolekcja sposób przetwarzania reprezentacji JSON, aby dodać poprawną instancję podtypu do listy. Aby dodać CoolSport przy zachowaniu nietkniętego kodu, wystarczy dodać funkcję modelu do kolekcji SportList i zwrócić nowy CoolSport, jeśli zawiera on "uselessAttr" (zobacz kod w moim pytaniu).

Wziąłem inną drogę i bezpośrednio przekazałem instancję CoolSport przez metodę add() kolekcji, zachowując w ten sposób jej podtyp.

Dzięki wszystkim za pomoc i nadzieję, że moja odpowiedź będzie pomagać innym :-)

5

Proszę, nie rób tego:

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

Czy to dobrze:

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

lub

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

Nigdy nie zrobię tego w zły sposób. Dziękuję za wskazanie mi tego błędu. Zobacz moje zaktualizowane pytanie, ponieważ zawiera ono prawdziwy problem, który mam. – jeromedt

1

definiowania model w swojej kolekcji jako „app.Sport”

więc kiedy pchają coolSport1.toJSON (), zostanie zainicjowany przy użyciu app.Sport model

, dlatego nie jest to instancja CoolSport, ale instancja Sportowa.

+0

Zauważyłem to samo kilka minut przed Tobą (zobacz moją odpowiedź poniżej) i rzeczywiście było to właściwe rozwiązanie. I cieszę się, że tam byłeś, gdybym nie znalazł go sam ;-) – jeromedt