Reflecting on JavaScript objects

I have been doing some more playing around with JavaScript recently, and wanted to do some reflection over JavaScript objects to see what functions they had, and then execute some of those functions. This is made fairly easy for us due to JavaScript’s use of associative arrays (from Wikipedia’s exampleobj.x = 10; is the same as obj["x"] = 10;).

First let’s embed some JavaScript into a local HTML file:

<script>
  var MyClass = function() {}
  MyClass.prototype = {
    aFunction: function() { return 1; },
    anotherFunction: function() { return 2; }        
  }
</script>

Here we have a basic MyClass class. We can use the for..in statement to enumerate through the items in this class:

for (var member in MyClass) {
  document.write(member + "<br/>");        
}

This writes “prototype” (plus line break) to the page in FireFox (not in IE7, but haven’t looked into why), which is the only thing defined for MyClass. You can also enumerate over MyClass.prototype to see what’s there. In my case I wanted to check and run methods from an instance of MyClass (which is initialised from the prototype):

var instanceOfMyClass = new MyClass();
for (var member in instanceOfMyClass) {
 document.write(member);
 document.write(": " + instanceOfMyClass[member]());
 document.write("<br/>");
}                 

Which displays the following (in both FireFox and IE7):

aFunction: 1
anotherFunction: 2

Here we access the functions in instanceOfMyClass by looking up the value associated with each member. One quick gotcha: the for..in enumeration in this case returns strings, not pointers to the member itself (so you can’t use member() to evaluate it).

Another option is to use the eval function to execute the method, but that isn’t quite as pretty as it involves building up strings (eval("instanceOfMyClass." + member + "()")).

Note we aren’t accounting for argument lists here. You might want to look at the Function class for getting more data about functions and their arguments. We also are not catering for members that are not functions. You can use typeof to filter out other values.

Comments