2012-03-13 11 views
26

Dada una instancia del modelo Backbone, ¿cómo puedo saber la "clase" (por así decirlo) de esta instancia?Obtener el modelo/clase de una instancia de modelo de Backbone

Por ejemplo:

class Car extends Backbone.Model 

mycar = new Car() 

Y lo que necesito es:

mycar.modelName # => 'Car' 
+1

Tiene que ser más específico. Un modelo podría tener múltiples vistas. La vista tiene la referencia .el que AFAIK debería ser suficiente, * si está considerando vistas *. Pero puede que eso no sea lo que preguntas. – JayC

+0

Ah, no importa. Estás hablando programáticamente. – JayC

+0

¿Por qué necesita el nombre de clase? ¿Crear un nuevo modelo del mismo tipo o acceder a una función de nivel de clase u otra cosa? Su pregunta interesante – websymphony

Respuesta

10

Es problemático en general, creo. Iba a sugerir algunas de las opciones mencionadas aquí (How do I get the name of an object's type in JavaScript?), pero tenía problemas con la primera opción. Siempre puede extender todos sus modelos para tener una función que arrojó un "nombre" para el modelo, pero puedo entender por qué puede encontrar eso menos que satisfactorio.

+1

Acepto, o lo resuelves manualmente como lo sugiere @JayC o estás hablando de una preocupación JS genérica muy antigua que aún no se resuelve. – fguillen

14

A partir de la escritura se puede obtener el nombre de la clase de un modelo de la siguiente manera:

model.constructor.name 

Esto funciona para mí en el navegador Chrome.

+15

Tenga en cuenta que esto no funcionará si tiene un minificador como Jammit, el constructor cambiará después del empaquetado. –

23

Intenté la sugerencia de Mitch pero en Chrome, model.constructor.name siempre es "" para mí.

Elegí en su lugar utilizar una convención. Ahora creo una propiedad de clase utilizando el segundo parámetro de extender que funciona de la siguiente manera:

directory.models.SomeModel = Backbone.Model.extend({ 
    // usual model instance stuff 
}, { 
    modelType: "SomeModel" // class property 
}); 

me di cuenta de que siempre se puede conseguir lo que quiero de esta manera:

var mt = model.constructor.modelType; 
0

Esto ya se resuelva en todos navegadores excepto IE, pero un relleno es fácil de hacer. La respuesta es Function.name:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name

Sin duda aprovechar esto! En las clases ES6, Function.name de un constructor es el nombre de la clase, por lo que en ES6:

class Car { /*...*/ } 
var c = new Car(); 
console.log(c.constructor.name); // "Car" 

en ES5 actual, no todas las bibliotecas se aprovechan de esto. La columna vertebral, por ejemplo, no. :(constructores Backbone son funciones anónimas, por lo

var m = new Backbone.Model(); 
console.log(m.constructor.name); // "undefined" :(

por desgracia. Al igual que otros de han dicho, si usted está utilizando la espina dorsal, que tendrá que hacer su propio sistema de nombres.

He aquí una función para polyfill .name:

// Polyfill for Function.name on browsers that do not support it (IE): 
// See: http://stackoverflow.com/questions/6903762/function-name-not-supported-in-ie 
if (!(function f() {}).name) { 
    Object.defineProperty(Function.prototype, 'name', { 
     get: function() { 
      var name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1]; 

      // For better performance only parse once, and then cache the 
      // result through a new accessor for repeated access. 
      Object.defineProperty(this, 'name', { value: name }); 

      return name; 
     } 
    }); 
} 
0

puede consultar el árbol de herencia (también conocido como cadena de prototipos) para la instancia de objeto como éste:

objeto .__ proto __.__ proto __.__ proto__

Puedes ver que hay disponible. Cualquier propiedad de nombre de tipo deberá ser agregada por usted a cada vista y/o modelo manualmente. Esta es la manera más limpia de ir. Recomiendo esto Simplemente agregue 'className: "MyCompany.MyProject.MyArea.MyView"' a cada una de sus vistas y/o modelos.

Si no se agrega una propiedad className a los objetos, hay una manera un poco hacky todavía conseguirlo (por ejemplo, para la salida de depuración):

Asumiendo que hacer algo como: "MyCompany.MyProject. MyArea.MyView = Backbone.View.extend ({"el nombre de clase de vista/modelo está en un nombre de var de espacio de nombres global. De la instancia de objeto no podemos alcanzar ese nombre var global. Por lo tanto, aunque no es realmente ideal, lo mejor que podemos hacer es atravesar el espacio de nombres en busca de la var:.

function findBackboneClassName(ns, object, prefix, depth) { 
    prefix = typeof prefix !== 'undefined' ? prefix : ""; 
    depth = typeof depth !== 'undefined' ? depth : 0; 
    if (depth > 5) return null; 

    for (i in ns) { 
     try { ns[i]; } catch (e) { continue; } 
     if (/top|window|document|parent|frames|self|chrome|form|theForm/.test(i)) continue; 
     //console.log(">" + prefix + "." + i + " " + typeof(ns[i])); 

     if (ns[i] == object.constructor) { 
      //console.log("Found:", prefix + "." + i); 
      return prefix + "." + i; 
     } 

     if (typeof (ns[i]) == "object") { 
      var r = findBackboneClassName(ns[i], object, prefix + (prefix != "" ? "." : "") + i, depth + 1); 
      if (r != null) return r; 
     } 
    } 
    return null; 
} 
findBackboneClassName(window, myBackboneViewInstance); 

lo ideal sería que usted está usando un espacio de nombres para sus tipos distintos de "ventana" Eso hace que sea mucho más limpio y más fácil de atravesar Simplemente reemplace "ventana" con la base de su espacio de nombres y pase el prefijo deseado si lo quiere con el prefijo correcto. También puedes eliminar un par de líneas como try..catch y if..continue.

findBackboneClassName(MyCompany.MyProject, myBackboneViewInstance, "MyCompany.MyProject"); 

El truco de hacer que el nombre de clase de objectInstance.constructor no funciona para la columna vertebral debido a la manera que lo hace la herencia. Todos los ctors tienen el mismo aspecto para mí: "function() {return parent.apply (this, arguments);}".

Cuestiones relacionadas