Methodize and functionize

Though the API docs seem to make no mention of it, there is this little gem sitting in Prototype 1.6.0:

Function.prototype.methodize = function() {
  if (this._methodized) return this._methodized;
  var __method = this;
  return this._methodized = function() {
    return __method.apply(null, [this].concat($A(arguments)));
  };
};

What that does is it returns a new function that calls the original function with its first argument set to whatever the current meaning of this is. This is how they now bind element methods to DOM objects:

// This takes an element as an argument
Element.visible = function(element) {
  return $(element).style.display != 'none';
};

// Convert is so it can be called as a method on elements
HTMLElement.prototype.visible = Element.visible.methodize()

This bit of trickery means you can myDiv.visible() rather than Element.visible(myDiv). We can make this work in reverse as well…

Function.prototype.functionize = function() {
  if (this._functionized) return this._functionized;
  var __method = this;
  return this._functionized = function() {
    var args = $A(arguments);
    return __method.apply(args.shift(), args);
  };
};

You could, for example use this if you have a particular iterator you keep reusing…

// If I keep doing this...
var safe = strings.map(function(s) { return s.stripScripts(); });

// I could do this instead...
var stripScripts = "".stripScripts.functionize();
var safe = strings.map(stripScripts);

Eh voilá! Much more legible code. You could equally do the above in a similar way with Reiterate, but I digress. The point is that you can do some pretty tricksy stuff with functions in JavaScript, and I’d guess that many web devs (myself included) are mostly unaware of the possibilities. Hopefully the new Prototype release will help folks expand their JS knowledge ever so slightly.