Modern JavaScript Development: Reflection in JavaScrpt

Sometimes you want to find out what members an object exposes. There’s a pretty simple way to do this. A simple for-in statement.


for(var member in obj){ alert(member); };

No really, that’s it. No “imports” or “using” statments. No complicated classes to memorize, no unwrapping or casting. Just for-in over an object. One caveat, this will show you ALL of the objects members and it doesn’t distinguish between members declared directly on the objects and members inherited through the objects prototype. What if you just want to find the methods on an object? I’ve created two helper functions that will return just the methods(functions) of any JavaScript object.

Object.prototype.getAllMethods = function(){
var memberArray = new Array();
for (var method in this) {
if (typeof this[method] == 'function') {
memberArray.push(method);
};
};
return memberArray;
};

Object.prototype.getOwnMethods = function(){
var memberArray = new Array();
for (var method in this) {
if (typeof this[method] == 'function' && this.hasOwnProperty(method)) {
memberArray.push(method);
};
};
return memberArray;
};

In the getOwnMethods function we use the hasOwnProperty function to discriminate between methods declared in the object and methods inherited through the prototype.

  • http://thinkweb2.com/projects/prototype/ kangax

    1) It’s better not to touch Object.prototype.
    2) Keep in mind, that “typeof” returns “function” for RegExp objects and NodeLists in webkit.
    3) hasOwnProperty is not supported in earlier versions of Safari
    4) “new Array()” is redundant, as array literal “[]” does the same thing

    Cheers,
    kangax

  • http://www.lazycoder.com Scott

    Great points kangax. These functions could easily be refactored into global functions that take a parameter that is the object to be inspected.

    re: new Array(); (sigh) That’s the static-typer in me showing through. Too many years of being a slave to the compiler.

  • http://scriptnode.com matt

    Well, globals are a bad choice too:

    http://yuiblog.com/blog/2006/06/01/global-domination/

    Maybe limit it to a single object and extend that.

  • http://programandosemcafeina.blogspot.com/ Tiago Albineli Motta

    @matt how could we make our objects extends this single object that has this behavior?

    • http://blog.dynamicprogrammer.com Hernan Garcia

      In order to avoid globals and the hassle of extending an object just for the sake of reflect on it. You wrap this functions in their own context/object.

      Reflector = {};
      Reflector.prototype.getAllMethodsOf = //rest of code here
      Reflector.prototype.getOwnMethodsOf = //rest of code here

      Now to use them just do Reflector.getAllMethodsOf(objectToReflectOn);

      I rename the methods so is clear that are acting in the argument and not in the Reflector object.

      H.

  • Chen Shangsong

    maybe FOR IN operator does not iterate “built-in” properties and functions? for example,

    var oo=new Object();

    now oo has many properties and functions like hasOwnProperty, prototype, etc, but the code bellow:

    for (var p in oo){
    alert(p);
    }

    alerts nothing.

  • http://crazyturkish.blogspot.com Tufandevrim

    very nice explanation of reflection in Java Script.