Sto cercando di implementare la mia versione della "Instance Store" in Backbone.js come descritto da Soundcloud nella loro recente post sul blog:Implementare javascript negozio di esempio restituendo un'istanza esistente dal costruttore
http://backstage.soundcloud.com/2012/06/building-the-next-soundcloud/
Rilevante Estratto:
Per risolvere questo, utilizziamo un costrutto che chiamiamo l'archivio di istanze. Questo negozio è un oggetto a cui si accede e si modifica in modo implicito ogni volta che viene chiamato un costruttore per un modello. Quando un modello viene costruito per la prima volta, si inietta nello store, utilizzando il suo id come chiave univoca. Se lo stesso costruttore di modello viene chiamato con lo stesso id, viene restituita l'istanza originale.
var s1 = new Sound({id: 123}),
s2 = new Sound({id: 123});
s1 === s2; // true, these are the exact same object.
Questo funziona a causa di una caratteristica sorprendentemente poco conosciuta di Javascript. Se un costruttore restituisce un oggetto, allora questo è il valore assegnato. Pertanto, se restituiamo un riferimento all'istanza creata in precedenza, otteniamo il comportamento desiderato. Dietro le quinte, il costruttore è fondamentalmente facendo questo:
var store = {};
function Sound(attributes) {
var id = attributes.id;
// check if this model has already been created
if (store[id]) {
// if yes, return that
return store[id];
}
// otherwise, store this instance
store[id] = this;
}
ho implementato la mia versione di questo sovrascrivendo la classe Backbone.Model di creare il mio costruttore.
var MyModel = Backbone.Model.extend({
constructor: function (attributes, options) {
var id = attributes ? attributes.id : undefined;
if (this.store[id]) {
return this.store[id];
}
Backbone.Model.prototype.constructor.apply(this, arguments);
if (id) {
this.store[id] = this;
}
}
});
var MyOtherModel = MyModel.extend({
store: {},
//other model stuff
});
Questo stava funzionando bene, ma qualcosa deve essere cambiato e ora è smesso di funzionare, e io sono sicuro perché. Le istanze appena create sono archiviate nell'oggetto del negozio senza alcun problema: ogni classe che estende la classe MyModel ha il proprio archivio vuoto per evitare collisioni di istanze di un tipo diverso con lo stesso id. L'istanza corretta viene anche recuperata senza problemi quando il costruttore viene chiamato con un ID esistente, tuttavia quando vengono restituiti dal costruttore il valore di ritorno viene ignorato. La mia comprensione dalle specifiche è che i costruttori possono restituire un oggetto - ma non una primitiva - e l'oggetto restituito verrà assegnato alla parte sinistra dell'istruzione di assegnazione quando il costruttore viene chiamato con il nuovo operatore. Ciò non sta accadendo, anche se il costruttore restituisce un oggetto, viene utilizzato l'oggetto vuoto creato dal nuovo operatore.
Alcune informazioni di debug. Non sei sicuro di quanto saranno utili queste informazioni. Questo è "questo" nel costruttore MyModel per un oggetto che viene istanziato per la prima volta.
child
_callbacks: Object
_escapedAttributes: Object
_previousAttributes: Object
_setting: false
attributes: Object
id: "4fd6140032a6e522f10009ac"
manufacturer_id: "4f4135ae32a6e52a53000001"
name: "Tide"
uniqueName: "tide"
__proto__: Object
cid: "c50"
collection: child
id: "4fd6140032a6e522f10009ac"
__proto__: ctor
constructor: function(){ parent.apply(this, arguments); }
defaults: Object
store: Object
url: function() {
urlRoot: function() {
__proto__: ctor
E questo è "questo" nel costruttore MyModel quando è un oggetto che viene restituito dal negozio esempio:
child
_callbacks: Object
_escapedAttributes: Object
_previousAttributes: Object
_setting: false
attributes: Object
_validate: function (attrs, options) {
bind: function (events, callback, context) {
change: function (options) {
changedAttributes: function (diff) {
clear: function (options) {
clone: function() {
constructor: function(){ parent.apply(this, arguments); }
defaults: Object
destroy: function (options) {
escape: function (attr) {
fetch: function (options) {
get: function (attr) {
has: function (attr) {
hasChanged: function (attr) {
idAttribute: "id"
initialize: function(){}
isNew: function() {
isValid: function() {
manufacturer_id: 0
name: ""
off: function (events, callback, context) {
on: function (events, callback, context) {
parse: function (resp, xhr) {
previous: function (attr) {
previousAttributes: function() {
save: function (key, value, options) {
set: function (key, value, options) {
store: Object
toJSON: function() {
trigger: function (events) {
unbind: function (events, callback, context) {
unset: function (attr, options) {
url: function() {
urlRoot: function() {
__proto__: Object
cid: "c141"
__proto__: ctor
constructor: function(){ parent.apply(this, arguments); }
defaults: Object
store: Object
url: function() {
urlRoot: function() {
__proto__: ctor
Cosa faccio notare è che gli attributi oggetto nel secondo si ha tutto il i metodi di un oggetto backbone incluso, che non dovrebbero essere. Inoltre non ha id, di nuovo non sono sicuro del perché. Speriamo che questo fornisca qualche intuizione. Grazie.
Potrebbe darci un deb ug view of MyModel? – Bergi
Sicuro. Scusa la mia ignoranza ma puoi specificare esattamente ciò di cui hai bisogno? JavaScript debugging qui, il mio debugging è generalmente costituito da istruzioni console.log. – Kareem
Sì, sarebbe fantastico. Suppongo che sia una funzione, quindi il suo codice e forse gli ambiti variabili a cui ha accesso potrebbero essere interessanti. – Bergi