Semantic constructors
One of the easiest ways to inspect an object is to type convert it to a string:
function foo() { return 'foo'; } foo + ''; // "function foo(){ return 'foo'; }" // or foo.toString(); // or String(foo);
When using Class.create from prototype.js, I often get annoyed by a meaningless result of constructor’s toString:
var Person = Class.create({ initialize: function(name) { this.name = name; }, speak: function(msg) { return this.name + ' says: ' + msg; } }) Person + ''; // "function klass() { this.initialize.apply(this, arguments); }" var Employee = Class.create(Person, { initialize: function($super, dept) { $super(); this.dept = dept; } }) Employee + ''; // "function klass() { this.initialize.apply(this, arguments); }"
As you can see, constructor’s default toString tells little about what’s going on under the hood. In fact, Class.create returns a generic constructor-function which only calls initialize method of a prototype. In other words it acts as a proxy. One of the ways to see actual constructor’s code is to inspect “initialize” method directly:
// nothing new here Person + ''; // "function klass() { this.initialize.apply(this, arguments); }" // and the actual code Person.prototype.initialize + ''; // "function (name) { this.name = name; }"
This is quite verbose, don’t you think? Let’s monkey patch Class.create a little:
Class.create = (function(original) { var fn = function() { var result = original.apply(null, arguments); result.toString = function() { return result.prototype.initialize.toString() }; return result; }; fn.toString = function(){ return original.toString() }; return fn; })(Class.create);
We simply redefine original Class.create with an “enhanced” version. New version “binds” toString of prototype.initialize as toString of constructor-function. As a bonus, it also takes care of a “wrapped” Class.create.toString itself - trying to be as unobtrusive as possible:
// monkey-patch Class.create first... // Person.toString now yields much more informative result Person + ''; // "function (name) { this.name = name; }" // Class.create code seems to be unchanged Class.create + ''; // outputs actual Class.create code
Pedro De Almeida said:
#This is really an interesting hack for developers that need more debugging functionalities. You should may be propose this feature to be part of the next Prototype release (by the way, are you a Prototype Team member? You seem to be actively working on it...)!
I don't know if it's feasible but your concept could be extended a little more: bind
toStringof prototype.initialize to another function that will output not only constructortoStringbut also all other class methods (which lacks terribly when you inspect objects with Firebug extension for Firefox):Anyway, nice work (as well)!