Reputation: 9407
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
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
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
Upvotes: 1
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