2011-07-01 16 views
37

Me gustaría plantear esto como una pregunta a this respuesta, pero parece que no puedo hacerlo, me disculpo.Extendiendo los valores predeterminados de una superclase modelo en Backbone.js

La extensión de los valores predeterminados para la subclase se refleja en la superclase. Esto parece frustrar el propósito y estoy más dispuesto a enumerar explícitamente los valores predeterminados de la superclase en la subclase para obtener la estructura que estoy buscando.

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

Este salidas:

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

No es lo que (ni, supongo, la op) quieren:

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

Respuesta

49

El problema es que Inventory.prototype.defaults y Extended.prototype.defaults tienen la misma referencia, porque no ha anulado la referencia.

Así que usted puede hacer esto en 2 maneras, tal vez más, pero sólo he encontrado este 2:

Editar: El primer ejemplo es incorrecta (ver comentarios); por favor refiérase al segundo.

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

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

o

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

Creo que la primera se ve más limpio.

+1

Gracias, @JCorcuera. Debería haber mirado más de cerca a _.extend() para resolver esto. Un problema con esta solución, sin embargo, es si cambio los valores predeterminados de ExtendedInventory a '{dog: 15, rabbit: 25}' El valor de ExtendedInventory de 'dog' se sobrescribe de nuevo a' 5'. Supongo que volveré a 'for (a en this.eiDefaults) {this.attributes [a] = this.eiDefaults [a];}' en el método 'initialize' de ExtendedInventory. – mcdoh

+0

@mcdoh mm tienes razón, pero el segundo funciona bien. – JCorcuera

+1

Tiene razón, por lo que parece que su segunda solución es la forma de hacerlo. ¡Gracias por tu ayuda! – mcdoh

0

Creo que tienes razón en que te gustaría asegúrese de que Inventory.prototype.defaults no cambie como resultado de agregar rabbit a ExtendedInventory.defaults. Mi herencia protoípica no es lo suficientemente buena como para explicar claramente por qué funciona lo siguiente, pero creo que hace lo que usted quiere que haga.

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

Un punto importante a recordar sobre el método _.extend es que el primer argumento es destination. Toma todos los atributos de los argumentos después del primer argumento y los coloca en el argumento de destino.

Otro punto es que ExtendedInventory.prototype.defaults === Inventory.prototype.defaults da como resultado verdadero, lo que significa que son el mismo objeto, por lo que si cambia el prototipo de ExtendedInventory cambiará el prototipo de Inventory (I ' Aunque no estoy seguro de por qué son iguales en primer lugar).

18

Creo que la mejor manera de resolverlo es utilizar el método _defaults_ de underscore.js.Esto permitirá que usted elimine los valores por defecto en la subclase del modelo:

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

ver este ejemplo:

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

3

Como una extensión de la respuesta de JCorcuera, si sus usos clase base (o pueden utilizar) una función para definir valores por defecto entonces esto va a funcionar muy bien:

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

el paletón de la llave es el uso de un funciton en el método por defecto niño y _.result()docs

0
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

creo underscore.js no se extienden valores profundamente. Debería usar Jquery $ .extend si tiene alguna matriz. Puede probarlo here

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

también debe darle primer parámetro "falsa" para hacer su trabajo correctamente. cuando es verdad, simplemente entrelazan entre sí.

0

Otra forma es utilizar la función de subrayado _.extend de lograr esto:

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

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