Let me disclaim straight away, this blog post is based on blatant copy of Eli Grey’s object.watch gist on GitHub. The small script proved so useful to me in a tight situation (I think last to last week) that with full acknowledgement of this being his work, I wanted to roll it up into a blog post.

Basically I was trying to debug an issue where an all important property of an object was being overwritten inadvertently by some code. A user action triggered loading of some scripts on the page dynamically and a callback was invoked when all the scripts were finished loading and initializing.

Thousands of lines of code were being executed between the time the user action triggered loading of the scripts (3-4 in number each containing around 600-3500+ lines of code) and by the time the callback was invoked after the scripts had finished loading and initializing themselves. At some point, one of these scripts was changing the value of a UI element’s attribute (and this attribute is referred to very commonly in those scripts, let’s say once every few lines of code).

I was potentially gasping at the prospect of having to debug every single of these lines to figure out the offending line of code.

But luckily at that point, I said to myself, hey how deeply I like the concept of properties in .Net, values attached to an object that look like attributes/variables, but behave as method calls when accessed/updated. You can put in any code to track who is accessing that property (and where) or who is changing it (and where).

And that immediately reminded me of Eli Grey’s script that enables something similar for object attributes in javascript. Using his code, you can essentially change any attribute on object to a property (in browsers with accessor support) whose value is returned or updated through accessor methods (Those from .Net background would easily figure out the difference between an attribute and property for an object. In .Net’s nomenclature, an attribute is a direct instance variable for an object, whereas a property is a combination of Get and Set accessors for a value, that value can be represented as an underlying attribute as is most common, or it might be a completely derived attribute whose value is not stored directly anywhere).

Without talking further, here’s the adapted version of his code:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }/*
* object.watch v1.0: Cross-browser object.watch
* http://code.eligrey.com/object.watch/
*
* By Elijah Grey, http://eligrey.com
*
* A shim that partially implements object.watch and object.unwatch
* in browsers that have accessor support.
*
* Public Domain.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/

/*
* Adapted by Rahul Singla (http://www.rahulsingla.com)
* to run as static methods on Object instead of
* being put into Object prototype.
*/

Object.watch = function (obj, prop, handler) {
var oldval = obj[prop], newval = oldval,
getter = function () {
return newval;
},
setter = function (val) {
oldval = newval;
return newval = handler.call(obj, prop, oldval, val);
};
if (delete obj[prop]) { // can’t watch constants
if (Object.defineProperty) // ECMAScript 5
Object.defineProperty(obj, prop, {
get: getter,
set: setter
});
else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
Object.prototype.__defineGetter__.call(obj, prop, getter);
Object.prototype.__defineSetter__.call(obj, prop, setter);
}
}
};

Object.unwatch = function (obj, prop) {
var val = obj[prop];
delete obj[prop]; // remove accessors
obj[prop] = val;
};{/syntaxhighlighter}

The only adaptation being that instead of adding the methods to Object prototype, I use them statically on Object. So if you want to monitor an attribute, let’s say title on an object variable, let’s say panel, you would do that as:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }Object.watch(panel, ‘title’, function(propName, oldVal, newVal) {
// your monitoring logic
});{/syntaxhighlighter}

Notice here panel is the actual object reference while title (the property to monitor) is passed as a string.

Chrome was my Development browser here and it supports accessors, so no issues with the browser support for this feature.

And as soon as I did that, put a debugger in the monitoring callback method, and analyzed the stack-trace when the debugger was hit (between the time of loading the scripts and invoking of the callback), I immediately was able to point out the problematic line and fix it within minutes (what could otherwise have taken many hours).

I realized then that many people might not be aware of this small but excellent piece of code that can greatly help in debugging tough situations in javascript and hence wanted to share my experience through this blog post.