获取对象类型

时间:2013-12-07 10:57:25

标签: javascript object

更新这里是最终的和正在运行的代码 - 以防有人发现它有用:jsfiddle

我把它写成了类型检测器。它在所有情况下都能很好地工作 - 到目前为止,无论我测试过什么,但只在一种情况下失败。

首先,这是片段:jsfiddle

var TypeOf = function ( thing ) {
    var typeOfThing = typeof thing;
    if ( typeOfThing === 'object' ) {
        typeOfThing = Object.prototype.toString.call(thing);
        if ( typeOfThing === '[object Object]') {
            if ( thing.constructor.name ) 
                typeOfThing = thing.constructor.name;
            else if ( thing.constructor.toString().charAt(0) === '[' ) 
                typeOfThing = typeOfThing.substring(8,typeOfThing.length - 1);
            else
                typeOfThing = thing.constructor.toString().match(/function\s*(\w+)/)[1];
        } else {
            typeOfThing = typeOfThing.substring(8,typeOfThing.length - 1);
        }
        return typeOfThing.toLowerCase();
    } else {
        return typeOfThing;
    }
}

问题在于,如果我在parse-time定义函数,那么它将完全正常工作:

function me () {};
var you = new me();
console.log('Type of you: ' + TypeOf(you));    // me

但是,如果我只是在run-time定义它,那么它将不起作用:

var me = function () {};
var you = new me();
console.log('Type of you: ' + TypeOf(you));    // nope

据我在解析时的情况看,constructor类似于function me () {},所以我可以使用/function\s*(\w+)/来获取它,但是在运行时情况下构造函数是function () {}

有什么方法可以让它发挥作用吗?此外,还有其他任何情况下此代码段可能无法检测到类型吗?

更新作为评论中提到的@lonesomeday,似乎我正在尝试获取匿名函数的名称。这对我来说有点吓人。这甚至可能吗?

更新,如下所述@jackson,似乎正确的输出应为function而不是me。这是真的正确吗?

3 个答案:

答案 0 :(得分:2)

你的测试确实成功了。该变量的类型确实是“函数”。

考虑到你的function me () {};在你的测试中的并置,你似乎已经预料到附近的语法略有修改的测试会产生类似的结果。但这种情况并非如此。 you没有理由拥有“我”的“阶级”(实际上不是一个阶级)。它只是一个常规的旧“功能”,仅此而已。

答案 1 :(得分:1)

该变量的构造函数的类型function,而不是me。您的第二个示例使用的是一个恰好由名为me的变量引用的匿名函数。

考虑如果将me重新分配给其他对象会发生什么:

var me = function () {};
var you = new me();
me = 10;
//what if TypeOf(you) had returned me? that would be confusing, because me is now an integer

如果您关心存储匿名函数的变量的名称(由于上述原因,这是一件很脆弱的事情),您可以使用此解决方法。

它找到 global 变量的名称,当前包含对象构造函数的引用:

function checkForAnAnonymousConstructor(o) {
    for(var f in window) {
        if(window[f] == o.constructor) return f;    
    }
}

me = function() { }
var you = new me();
console.log(checkForAnAnonymousConstructor(you)); //-> me

//This only works whilst the reference is current
me = 10
console.log(checkForAnAnonymousConstructor(you));// -> undefined

http://jsfiddle.net/nE9eP/2

答案 2 :(得分:0)

你必须考虑有关JavaScript函数的一个非常重要的观点,这是你定义它们的方式。当你执行var me = function () {}时,你实际上创建了一个匿名函数,一个没有任何名字的函数,然后将它分配给一个变量。 当你创建这样的函数时:

function myfunc(){}

实际上就像:

var myfunc = function myfunc(){};

这里最重要的一点是,函数的名称不是唯一的,你可以用同一个名字创建几个函数。

var Func1 = function myfuncname(){ this.name = 'Func1'; };

var Func2 = function myfuncname(){ this.name = 'Func2'; };

如您所见,我们有两个不同的功能,如果您使用TypeOf功能,结果是相同的:

TypeOf(new Func1) -> myfuncname

以及

TypeOf(new Func2) -> myfuncname

顺便说一下,你的TypeOf功能是完全正确的,但这里唯一的问题是,如果你想得到正确的结果,你必须改变:

var me = function () {};
var you = new me();
console.log('Type of you: ' + TypeOf(you));

为:

var me = function me() {};
var you = new me();
console.log('Type of you: ' + TypeOf(you));

我之前已经完成了这项艰巨的任务,我很乐意分享你需要的任何东西。