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
Did you like this? Donations are welcome
comments powered by Disqus