Mahdi
Mahdi

Reputation: 9407

Get the object type

Update here is the final and working code -- just in case if somebody found it helpful: jsfiddle

I've written this as the type detector. It works very well in all cases -- so far whatever I've tested, but fails only in one case.

First, here is the snippet: 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;
    }
}

The problem is that if I define the function at parse-time then it will work perfectly fine:

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

However if I just define it at run-time, then it won't work:

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

As far as I can see in the parse-time case the constructor is something like function me () {}, so I can get it with /function\s*(\w+)/, however in the run-time case the constructor is function () {}.

Is there any way to get this to work? And also, are there any other cases that this snippet might potentially fail to detect the type?

Update as @lonesomeday mentioned in the comments, it seems that I'm trying to get the name of an anonymous function. That looks a little bit scary to me. Is that even possible?

Update as @jackson said below, it seems that the correct output should be function not me. Is that really correct?

Upvotes: 1

Views: 86

Answers (3)

Mehran Hatami
Mehran Hatami

Reputation: 12961

you have to consider a very important point regarding JavaScript functions, which is the way you define them. when you do var me = function () {} you have actually created a anonymous function, a function without any name and then assigned it to a variable. when you create a function like this:

function myfunc(){}

it is actually like:

var myfunc = function myfunc(){};

the most important point here is, function's name is not unique, you can create several functions with the same name.

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

or

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

as you see here we have 2 different function which if you use your TypeOf function the result is the same:

TypeOf(new Func1) -> myfuncname

and also

TypeOf(new Func2) -> myfuncname

BTW, your TypeOf function is perfectly correct but the only problem here is, if you want to get the correct result you have to change:

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

to:

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

I have gone thru this arduous task before and I would be happy to share anything you need.

Upvotes: 0

joews
joews

Reputation: 30310

The type of that variable's constructor is a function, not me. Your second example uses an anonymous function that happens to be referenced by a variable called me.

Think about what would happen if you reassigned me to a different object:

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

If you do care about the name of a variable that stored an anonymous function (which is a fragile thing to do for the aforementioned reason), you could use this workaround.

It find the name of the global variable that currently holds a reference to an object's constructor:

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

Upvotes: 1

Jackson Ray Hamilton
Jackson Ray Hamilton

Reputation: 9466

Your test actually succeeded. The type of that variable is indeed "function".

Given the juxtaposition of your function me () {}; in your tests, you seem to have expected that the nearby test with slightly-modified syntax would have a similar result. But this is not the case. There is no reason why you would have the "class" (not actually a class) of "me". It is just a regular old "function", nothing more.

Upvotes: 2

Related Questions