获取Backbone Model实例的模型/类名

时间:2012-03-13 14:26:08

标签: javascript backbone.js coffeescript

鉴于Backbone模型的一个实例,我怎么知道这个实例的“类”(可以这么说)?

例如:

class Car extends Backbone.Model

mycar = new Car()

我需要的是:

mycar.modelName # => 'Car'

5 个答案:

答案 0 :(得分:23)

我尝试了Mitch的建议,但在Chrome中,对我来说,model.constructor.name总是""

我选择使用约定。我现在使用extend的第二个参数创建一个类属性,其工作方式如下:

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

我发现我总能得到我想要的东西:

var mt = model.constructor.modelType;

答案 1 :(得分:14)

在撰写本文时,您可以通过执行以下操作获取模型的类名:

model.constructor.name

这适用于Chrome浏览器。

答案 2 :(得分:10)

我认为这一般存在问题。我打算提出一些这里提到的选项(How do I get the name of an object's type in JavaScript?),但我遇到了第一个选项的问题。您可以随时扩展所有模型,使其具有返回模型“名称”的功能,但我可以理解为什么您可能会发现不太满意。

答案 3 :(得分:0)

除了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中,并非所有库都利用了这一点。例如,Backbone没有。 :( Backbone构造函数是匿名函数,所以

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

不幸。和其他人一样,如果您使用Backbone,您必须制作自己的命名系统。

这是一个用于Function.name:

的polyfill
// 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;
        }
    });
}

答案 4 :(得分:0)

您可以查询对象实例的继承树(也称为原型链),如下所示:

对象.__原__.__原__.__原__

您可以看到可用的内容。您必须手动将任何类型名称属性添加到每个视图和/或模型。这是最干净的方法。我推荐这个。只需在每个视图和/或模型中添加'className:“MyCompany.MyProject.MyArea.MyView”即可。

如果你没有为你的对象添加一个className属性,那么仍有一种方法可以获得它(例如用于调试输出):

假设您执行以下操作:“MyCompany.MyProject.MyArea.MyView = Backbone.View.extend({”视图/模型类名称位于全局命名空间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);

理想情况下,您为“window”以外的类型使用命名空间。这使得它更干净,更容易遍历。您只需将“窗口”替换为命名空间的基础,并在需要正确添加前缀时传入所需的前缀。你也可以删除一些像try..catch和if..continue。

这样的行
findBackboneClassName(MyCompany.MyProject, myBackboneViewInstance, "MyCompany.MyProject");

从objectInstance.constructor获取类名的技巧因为它继承的方式而不适用于主干。所有ctors对我来说都是一样的:“function(){return parent.apply(this,arguments);}”。