1

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?

6
  • 2
    You are essentially asking how to get the name of an anonymous function. That is, by definition, rather hard to do. Commented Dec 7, 2013 at 11:02
  • @lonesomeday Thanks, you're right, I will try to rephrase the question title as well. Commented Dec 7, 2013 at 11:03
  • Note also that you could do thing.constructor.name in browsers that support it (!IE, basically). By the way, when I say "rather hard to do" above, I actually mean "by definition impossible". Commented Dec 7, 2013 at 11:06
  • @lonesomeday I actually have it up there in the code, but that didn't work also ... Do you mean I should implement it in another way? Commented Dec 7, 2013 at 11:08
  • Just my $0.02: I really think you're trying to solve the wrong problem. It's one thing to make a compiler check all the types (and that's what TypeScript is about). It's another thing to check all the types in run-time - it's very... weird, to say the least. Commented Dec 7, 2013 at 11:25

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Hah! Is that really correct? ... Let me add it to the original question! but good point, thanks!
Yes. Thinking in terms of C, you could consider me a "pointer" to a regular function. In JavaScript, you just happen to be able to invoke any referenced function by appending parens to end of the variable that references it.
1

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

4 Comments

Nice, thanks for the effort. I will wait a bit more to see if I get more answers! Jackson actually had a good point tho ...
Yes, his is the right answer to "what is the type of this variable" - this is subtly different, but it match what you originally expected.
This guy -> stackoverflow.com/a/338053/1468130 actually prefers the var x = function() {}; approach because it lets him control visibility. To each his own. The "validity" of that approach kind of depends on the architecture of your application. Given the outcome of toString() I am led to believe that that is not how the language is designed or should be approached, though the typeof operator is so lousy that it's difficult for me to be confident in my opinion. (Seems like they didn't really care about types when they designed JS, so to a certain extent that leaves it up to us.)
@joews Hey! Even tho if you actually answered what I was asking for, but I still think that Jackson's answer is more correct, so I just went for that. Thanks again for your time and explanation. :)
0

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.

5 Comments

Well, you're somehow right, but first you shouldn't give a name to anonymous functions I guess -- like mufuncname(), it's redundant and probably confusing, and even if you want to do that then you should not come up with a same name for two different functions. But thanks anyways for the heads-up :)
For me, the result of TypeOf(Func1) and TypeOf(Func2) was "function" for each. jsfiddle.net/9fsqy/1.
Also, the names of functions, in named function expressions, are only available within the scope of said functions. See the third block of code on this answer: stackoverflow.com/a/338053/1468130
Sorry about the mistake, what I meant is TypeOf(new Func1) and TypeOf(new Func2) would be the same
I did the same task to be used in my JavaScript team codes but my TypeOf function was to use only for objects of our JavaScript class types. I had asked all team members to use appropriate names for our JavaScript classes(Functions). My main point is if your functions have no name or the names are duplicated your TypeOf function would not be able to return a appropriate result.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.