Учитывая экземпляр модели Backbone, как я могу узнать "класс" (так сказать) этого экземпляра?
Например:
class Car extends Backbone.Model
mycar = new Car()
И мне нужно:
mycar.modelName # => 'Car'
Учитывая экземпляр модели Backbone, как я могу узнать "класс" (так сказать) этого экземпляра?
Например:
class Car extends Backbone.Model
mycar = new Car()
И мне нужно:
mycar.modelName # => 'Car'
Это проблематично вообще, я думаю. Я собирался предложить некоторые из упомянутых здесь опций (Как получить имя типа объекта в JavaScript?), но у меня возникли проблемы с первым вариантом. Вы всегда можете расширить все свои модели, чтобы иметь функцию, которая вернула "имя" для модели, но я могу понять, почему вы можете найти это менее чем удовлетворительным.
Я попробовал предложение Митча, но в Chrome, model.constructor.name всегда ""
для меня.
Вместо этого я решил использовать соглашение. Теперь я создаю свойство класса, используя второй параметр расширения, который работает следующим образом:
directory.models.SomeModel = Backbone.Model.extend({
// usual model instance stuff
}, {
modelType: "SomeModel" // class property
});
Я обнаружил, что всегда могу получить то, что хочу:
var mt = model.constructor.modelType;
С момента написания вы можете получить имя класса модели, выполнив следующие действия:
model.constructor.name
Это работает для меня в браузере Chrome.
Это уже разрешено во всех браузерах, кроме IE, но polyfill легко сделать. Ответ Function.name
:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
Определенно воспользуйтесь этим! В классах ES6 конструктор Function.name - это имя класса, поэтому в ES6:
class Car { /*...*/ }
var c = new Car();
console.log(c.constructor.name); // "Car"
В текущем ES5 не все библиотеки используют это. Например, магистраль, нет.:( Магистральные Конструкторы анонимные функции, так что
var m = new Backbone.Model();
console.log(m.constructor.name); // "undefined" :(
к сожалению. Как и другие, если вы используете Backbone, вам нужно будет создать собственную систему именования.
Здесь polyfill для Function.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;
}
});
}
Вы можете запросить дерево наследования (aka prototype chain) для вашего экземпляра объекта следующим образом:
объект.__ прото __.__ прото __.__ прото __
Вы можете видеть, что доступно. Любое свойство имени типа должно быть добавлено вами для каждого вида и/или модели вручную. Это самый чистый путь. Я рекомендую это. Просто добавьте "className:" MyCompany.MyProject.MyArea.MyView "к каждому из ваших представлений и/или моделей.
Если вы не добавляете свойство className к своим объектам, есть немного хакерский способ его получить (например, для целей вывода отладки):
Предполагая, что вы делаете что-то вроде: "MyCompany.MyProject.MyArea.MyView = Backbone.View.extend({" имя класса/класса в глобальном имени var names пространства имен ". Из экземпляра объекта мы не можем достичь этого глобального var имя. Поэтому, хотя это и не очень идеально, мы можем лучше всего пересечь пространство имен, ища 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);
В идеале вы используете пространство имен для своих типов, отличных от "окна". Это делает его намного чище и легче проходит. Вы просто заменяете "окно" базой своего пространства имен и передаете желаемый префикс, если хотите, чтобы он был префикс правильно. Вы также можете удалить пару строк, например, try..catch и if..continue.
findBackboneClassName(MyCompany.MyProject, myBackboneViewInstance, "MyCompany.MyProject");
Трюк получения имени класса из объекта ObjectInstance.constructor не работает для магистрали из-за того, как он наследует. Все ctors выглядят одинаково для меня: "function() {return parent.apply(this, arguments);}".