Get Class of an Instance

Posted by Sean on May 08, 2009 under Javascript

Have you ever wanted to get the class name of an object, maybe to check what instance it is of, or maybe to use the name for something? I was in need of exactly that, so I set out to do so last night. I started by asking Stack Overflow , and no one gave me an answer, so I pondered about it a bit. I started paying attention to the Hash object.

I knew that inside a class function, this.constructor would reveal the function that makes new intances of that class. But that function is anonymous, so I couldn't ask for the Function.name property. But! But, if I have a value, I can check an object for the key of that value.

 
var Poop = new Class({
    get_class: function() {
        return $H(window).keyOf(this.constructor);
    }   
});

This made me super excited, cause now I can build an interface that uses the class name for a particular process. And when I decided to write about it, I figured I'd make sure this method worked in all cases. And realized a case where this wouldn't work: Drag.Move (Obj.Anything, actually).

Finding in Namespaces

The original function scans the window object for the class that has been declared. But what if you created the class inside some namespace? You could change the function to check the Hash of the namespace, but I didn't like that. So I pulled together a new Hash function that searchs a Hash recursively for a ke y (keyOf only goes one level).

 
Hash.implement({
    findKey: function(key) {  
        var val = this.keyOf(key);
        if(val) return val;
        for(var prop in this) {   
            if(this.hasOwnProperty(prop) && typeof this[prop] == 'object') {
                val = $H(this[prop]).findKey(key);
                if(val) {
                 return this.findKey(this[prop]) + '.' + val;
                }
            }
        }
    }   
});

A Class Extra

Now equipped with Hash.findKey, I altered the get_class function to work anywhere. This is a class that you can include in your Implements option for any new Class:

 
var GetClass = new Class({
    get_class: function() {
        return $H(window).keyOf(this.constructor);
    }   
});

With the Hash method, and this new class included in your scripts, this simple example works out:

 
var Foo = {};
Foo.Bar = new Class({ 
    Implements: [GetClass]
});
var a = new Foo.Bar();
a.get_class(); //returns 'Foo.Bar'

I'd love to hear any uses you might have for this in the comments .

Interested in Javascript or MooTools? Subscribe to my articles for free.

7 Comments

  1. Awesome trick, I had discarded this as "not possible" a while ago - I'm glad you aren't a quitter like me.

  2. Just curious, what would you use this for? What happens with inheritance? What does window do if you have a compatibility alias?

    var Foo = new Class();
    var oldNameForFoo = Foo;

  3. @Aaron:

    My use for it:

    var DataModel = new Class({
    	tableize: function() {
    		return this.get_class().toLowerCase() + 's';
    	},
    	insert: function() {
            this.db.query('insert into '+this.tableize()+' ...');
        }
    });
    

    I'm doing some AIR development, and I'm used to my Models being able to insert themselves, so I want a DataModel class that can be extended and be able to tableize it's own name for inserts, updates, selects, etc.

    With inheritance, (I'd need to confirm this) it should return the class name of which class you instantiated. It checks for this.constructor.

    If you made an alias to the class, then it would do just as keyOf and indexOf always do: return the first found case.

  4. Very cool!

  5. second that...

  6. Very nice work! I found a problem Hash.findKey when extending a class while using namespaces.

    var com = {};
    com.Human = new Class({ Implements: [GetClass], ...});
    com.Employee = new Human({ Extends: com.Human, ...});
    
    var kevin = new com.Employee();
    kevin.get_class();  //returns v.constructor
    

    I changed:

    if(val) return val;

    to:

    if(val && val != 'constructor') return val;

    and all works fine for me.

  7. This is a great tip. I'm using it extensively in my javascript unit tests.

Add a Comment

Search

Categories

Treats

See all »