Получить имя модели / класса экземпляра Backbone Model - PullRequest
26 голосов
/ 13 марта 2012

Учитывая экземпляр модели Backbone, как я могу узнать «класс» (так сказать) этого экземпляра?

Например:

class Car extends Backbone.Model

mycar = new Car()

И что мне нужно, так это:

mycar.modelName # => 'Car'

Ответы [ 5 ]

23 голосов
/ 05 сентября 2012

Я попробовал предложение Митча, но в Chrome model.constructor.name всегда для меня "".

Я выбрал вместо этого соглашение. Теперь я создаю свойство класса, используя второй параметр extension, который работает следующим образом:

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

Я обнаружил, что всегда могу получить то, что хочу, вот так:

var mt = model.constructor.modelType;
14 голосов
/ 26 июля 2012

На момент написания вы можете получить имя класса модели, выполнив следующие действия:

model.constructor.name

Это работает для меня в браузере Chrome.

10 голосов
/ 13 марта 2012

Это вообще проблематично, я думаю.Я собирался предложить некоторые из упомянутых здесь опций ( Как мне получить имя типа объекта в JavaScript? ), но у меня были проблемы с первым вариантом.Вы всегда можете расширить все свои модели, чтобы иметь функцию, которая возвращает «имя» для модели, но я могу понять, почему вы можете найти это менее чем удовлетворительным.

0 голосов
/ 20 января 2015

Вы можете запросить дерево наследования (также называемое цепочкой прототипов) для вашего экземпляра объекта следующим образом:

object .__ proto __.__ proto __.__ proto __

Вы можете увидеть, что доступно.Любое свойство имени типа должно быть добавлено вами к каждому виду и / или модели вручную.Это самый чистый путь.Я рекомендую это.Просто добавьте 'className: "MyCompany.MyProject.MyArea.MyView" "к каждому из ваших представлений и / или моделей.

Если вы не добавляете свойство className к своим объектам, есть немного хакерский способчтобы получить его (например, для целей отладки):

Предполагая, что вы делаете что-то вроде: "MyCompany.MyProject.MyArea.MyView = Backbone.View.extend ({" имя класса представления / модели находится вглобальное имя переменной пространства имен. Из экземпляра объекта мы не можем получить это глобальное имя переменной. Поэтому, хотя это и не совсем идеально, лучшее, что мы можем сделать, это пересечь пространство имен в поисках переменной:

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);}".

0 голосов
/ 04 декабря 2014

Это уже решено во всех браузерах, кроме IE, но сделать полифилл легко. Ответ 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, вам придется создать собственную систему имен.

Вот многозаполнение для Function.name:

// Polyfill for Function.name on browsers that do not support it (IE):
// See: /4255821/imya-funktsii-ne-podderzhivaetsya-v-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;
        }
    });
}
...