web-dev-qa-db-de.com

Erweitern der Standardwerte einer Model-Superklasse in Backbone.js

Ich möchte dies als Frage an this antworten, aber ich kann es nicht scheinen, ich entschuldige mich.

Das Erweitern der Standardwerte für die Unterklasse spiegelt sich in der Oberklasse wider. Dies scheint den Zweck zu zerstören, und ich bin eher geneigt, die Standardwerte der Superklasse in der Unterklasse explizit aufzulisten, um die gewünschte Struktur zu erhalten.

var Inventory = Backbone.Model.extend({
    defaults: {
        cat: 3,
        dog: 5
    }
});

var ExtendedInventory = Inventory.extend({
});

_.extend(ExtendedInventory.prototype.defaults, {rabbit: 25});

var i = new Inventory();
var ei = new ExtendedInventory();
console.log(i.attributes);
console.log(ei.attributes);

Dies gibt aus:

{cat: 3, dog: 5, rabbit: 25}
{cat: 3, dog: 5, rabbit: 25}

Nicht was ich (noch nehme ich an, die op ) will:

{cat: 3, dog: 5}
{cat: 3, dog: 5, rabbit: 25}
37
mcdoh

Das Problem ist, dass Inventory.prototype.defaults und Extended.prototype.defaults dieselbe Referenz haben, da Sie die Referenz nicht überschrieben haben.

Sie können dies auf zwei Arten tun, vielleicht mehr, aber ich habe nur diese 2 gefunden:

Bearbeiten: Das erste Beispiel ist falsch (siehe Kommentare). Bitte beziehen Sie sich auf den zweiten.

var ExtendedInventory = Inventory.extend({
    defaults: {
        rabit:25
    }
});

_.extend(ExtendedInventory.prototype.defaults, Inventory.prototype.defaults);

oder

var ExtendedInventory = Inventory.extend({
    defaults: _.extend({},Inventory.prototype.defaults,
         {rabit:25}
    )
});

Ich denke der erste sieht sauberer aus.

50
JCorcuera

Ich denke, der beste Weg, es zu lösen, ist die _.defaults-Methode von underscore.js. Auf diese Weise können Sie Standardwerte in Ihrer Modellunterklasse überschreiben:

_.defaults(ExtendedInventory.prototype.defaults, 
           Inventory.prototype.defaults);

Siehe dieses Beispiel:

http://jsfiddle.net/mattfreer/xLK5D/

18
b73

Als Erweiterung der Antwort von JCorcuera: Wenn Ihre Basisklasse eine Funktion zum Definieren von Standardwerten verwendet (oder verwenden kann), wird dies gut funktionieren:

   defaults: function() {                                     
     return _.extend( _.result(Slot.prototype, 'defaults'),{  
       kind_id: 6,                                  
       otherthing: 'yello'  
       // add in your extended defaults here                                
   })}                                                      

das Schlüsselbit ist die Verwendung einer Funktion in der Kindervorgabemethode und _.result()docs

3
ErichBSchulz

Eine andere Möglichkeit besteht darin, die _.extend-Funktion von Unterstrich zu verwenden, um dies zu erreichen:

var SuperClass = Backbone.Model.extend({
  baseDefaults: {
    baseProp1: val,
    baseProp2: val2
  }
});

var SubClass = SuperClass.extend({
  defaults: _.extend({
    prop1: val,
    prop2: val2
  }, SuperClass.prototype.baseDefaults)
})
0
dipole_moment

Ich denke, Sie haben Recht, dass Sie sicherstellen möchten, dass Inventory.prototype.defaults sich nicht ändert, wenn Sie Kaninchen zu ExtendedInventory.defaults hinzufügen. Meine protoypische Vererbung ist nicht gut genug, um klar zu erklären, warum das Folgende funktioniert, aber ich denke, das tut, was Sie wollen.

ExtendedInventory.defaults = {}
_.extend(ExtendedInventory.defaults, ExtendedInventory.prototype.defaults, {rabbit: 25});

Ein wichtiger Punkt bei der _.extend-Methode ist, dass das erste Argument destination ist. Es nimmt alle Attribute aus den Argumenten nach dem ersten Argument an und platziert sie im Zielargument.

Ein weiterer Punkt ist, dass ExtendedInventory.prototype.defaults === Inventory.prototype.defaults zu true führt, was bedeutet, dass sie dasselbe Objekt sind. Wenn Sie also den Prototyp von ExtendedInventory ändern, ändern Sie den Prototyp von Inventory sie sind zwar in erster Linie gleichwertig).

0
c3rin

Ich denke, underscore.js reicht nicht tief aus. Sie sollten Jquery $ .extend verwenden, wenn Sie ein Array haben. Sie können es versuchen hier

var basemodel = Backbone.Model.extend({
  defaults:{a:{"1":"1","2":4,"4":5},b:2}
}
);

var model1 = basemodel.extend({
    defaults: $.extend(false,basemodel.prototype.defaults,{a:{"1":1,"2":2},b:{"xx":13}})
});


var model2 = basemodel.extend({
    defaults: $.extend(false,basemodel.prototype.defaults,{a:{"1":1,"2":2},z:13})
});



var m1 = new model1();
var m2 = new model2();


alert(JSON.stringify(m1.toJSON()));
alert(JSON.stringify(m2.toJSON()));

Sie sollten auch den ersten Parameter "false" angeben, um Ihre Arbeit korrekt auszuführen. Wenn es wahr ist, verschränken Sie sich einfach.

0
sanji_san
var MoveToolModel = ToolModel.extend({
    extendDefaults: {
        cursor: 'move'
    },
    initialize: function() {
        ToolModel.prototype.initialize.apply(this, arguments);
        this.defaults = _.extend({}, this.defaults, this.extendDefaults);
    },
    draw: function(canvasContext, data) {
        //drag
    }
});
0
Oleksandr Knyga