Using Recursion to implement Reflection in Javascript

Francis Pham
2 min readSep 16, 2015

--

Many CS languages have reflection built in, but javascript only has limited functionality to reflect on its code. Reflection is the ability to provide to the programmer useful info about any code, like a function or class. To reflect a class, you would need to output the methods and properties that each class implements. Since classes’ prototypes are chained, using recursion is ideal to solve this problem. Implementing reflection for prototypes is relatively easy: the function should call Object.keys() to get the current class’ properties and recursively call itself until the base case is reached, which is when getPrototypeOf(prototype) is null.

This website doesn’t allow multiple spacing/ tabs, so see jsbin.com for the formatted code.

function reflector(obj) {

if (Object.getPrototypeOf(obj) !== null) { // the recursive base case is Object, whose prototype is null;

reflector(Object.getPrototypeOf(obj));

}

console.log(‘Class: ‘ + obj.constructor.name);

// get the properties in the current prototype;

console.log(‘prototype properties: ‘ + Object.keys(obj));

}

However, this only gets the public properties defined on the class prototype. To get the privileged and instance methods defined in the constructor, the problem gets more complicated since Object.keys() gives all privileged/ instance methods regardless if they’re defined in the current class or a superclass. You may wonder why Object.keys() is climbing the inheritance tree when the documentation says it doesn’t. Actually, that function is still only looking at the current class because all privileged & instance methods are assigned to EACH instance, not to the instances’ class prototype, regardless of where those methods are defined. So to get the privileged & instance methods, one must compare the methods of an INSTANCE of the current class to those methods of an INSTANCE of the super class.

function reflector(obj) {

if (obj instanceof obj.constructor) { // if obj is an instance, call reflector with its prototype without printing;

reflector(Object.getPrototypeOf(obj));

} else {

var theseKeys;

if (Object.getPrototypeOf(obj) !== null) {

var superKeys = reflector(Object.getPrototypeOf(obj));

// if prototype is not null (aka: obj is not Object), recursively call reflector;

// UNROLL: use return values of later recursions to compare Subclass’ properties with the Superclass’ properties;

var diffKeys = Object.keys(new obj.constructor());

diffKeys = diffKeys.filter(function(val) { return !superKeys.some(function(sup) { return sup === val; });

});

console.log(‘Class: ‘ + obj.constructor.name);

console.log(‘instance properties: ‘ + diffKeys);

theseKeys = Object.keys(obj);

} else { // the recursive base case is Object, whose prototype is null;

console.log(‘Class: ‘ + obj.constructor.name);

theseKeys = Object.getOwnPropertyNames(Object.prototype);

}

console.log(‘prototype properties: ‘ + theseKeys);

return Object.keys(new obj.constructor());

}

}

Javascript provides 3 functions to iterate through the properties of an object. Object.keys() gets the enumerable properties of the current class only. The for … in loop gets the enumerable properties in the current class AND in it’s prototype chain. The Object.getOwnPropertyNames gets both enumerable & non-enumerable properties in the current class only. See the MDN page for more info on property enumerability and ownership: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties

Now with this reflector function, you can reflect on the public & inherited properties of an object’s prototype and the privileged & instance properties of an object instance.

--

--