web-dev-qa-db-fra.com

Extension des valeurs par défaut d'une super classe de modèles dans Backbone.js

Je voudrais poser ceci comme une question à ceci répondre mais je n'arrive pas à le faire, je m'excuse.

L'extension des valeurs par défaut pour la sous-classe est reflétée dans la superclasse. Cela semble aller à l'encontre du but recherché et je suis plus à même d'énumérer explicitement les valeurs par défaut de la superclasse dans la sous-classe pour obtenir la structure que je cherche.

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);

Cela génère:

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

Pas ce que je (ni, je suppose, le op ) veux:

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

Le problème est que Inventory.prototype.defaults et Extended.prototype.defaults ont la même référence, car vous n'avez pas remplacé la référence.

Donc vous pouvez le faire de 2 manières, peut-être plus mais je n'ai trouvé que 2:

Edit: Le premier exemple est incorrect (voir les commentaires); s'il vous plaît se référer à la seconde.

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

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

ou

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

Je pense que le premier a l'air plus propre.

50
JCorcuera

Je pense que la meilleure façon de le résoudre est d'utiliser la méthode _.defaults de underscore.js. Cela vous permettra de remplacer les valeurs par défaut dans votre sous-classe Model:

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

Voir cet exemple:

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

18
b73

En tant qu'extension de la réponse de JCorcuera, si votre classe de base utilise (ou peut utiliser) une fonction pour définir les valeurs par défaut, cela fonctionnera parfaitement:

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

le bit clé étant l'utilisation d'une fonction dans la méthode par défaut de l'enfant et la fonction _.result()docs

3
ErichBSchulz

Une autre méthode consiste à utiliser la fonction _.extend de soulignement:

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

Je pense que vous avez raison de vouloir vous assurer que Inventory.prototype.defaults ne change pas à la suite de l'ajout d'un lapin à ExtendedInventory.defaults. Mon héritage protoïpique n'est pas assez bon pour expliquer clairement pourquoi le sous-principe fonctionne, mais je pense que cela fait ce que vous voulez.

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

Un point important à retenir sur la méthode _.extend est que le premier argument est destination. Il prend tous les attributs des arguments après le premier argument et les place dans l'argument de destination.

Un autre point est que ExtendedInventory.prototype.defaults === Inventory.prototype.defaults renvoie true, ce qui signifie qu’il s’agit du même objet. Par conséquent, si vous modifiez le prototype de ExtendedInventory, vous modifiez celui de Inventory (je ne sais pas pourquoi ils sont égaux en premier lieu).

0
c3rin

Je pense que underscore.js n'allonge pas les valeurs en profondeur. Vous devez utiliser Jquery $ .extend si vous avez un tableau. Vous pouvez l'essayer ici

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()));

Aussi, vous devriez donner le premier paramètre "false" pour faire votre travail correctement. quand c'est vrai, il suffit de s'entrelacer.

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