As I suspect is common with many Prototype shops, over here at, we're making HEAVY use of Function#bind().  We've been
using a custom version of the bind() method for a while now, and I've
recently added a couple enhancements  that I'd like to get people's
opinions on - especially that of the Prototype team.

I've attached a commented version of our implementation below (we run
this after importing the Prototype library, so it just overwrites the
Prototype code).  The motivation for this implementation is as

- bind() is so ubiquitous for us that performance is a top priority.
We're willing to have a bit more code here to make things run faster.
In particular, 99% of our use of bind() is simply to bind a function
to an object, without binding any arguments (e.g. "...bind
(someObject)").  So special-casing that situation makes sense.

- Stepping through bound functions is painful because you constantly
have to step-into/out-of the $A method.  It's possible to improve
performance *and* make stepping through code easier by inlining the
code that sets up the args array.

- Inspecting functions created by bind() (e.g. "someFunction.toString
()") is never helpful.  Provide a way to "unbind" a function to get at
the original method.

Aside from the obvious increase in code size (which isn't *that* much
when the code is compacted - adds ~100-150 bytes), are there any
disadvantages/weaknesses to this implementation?  Would it make sense
to migrate some or all of these changes into the Prototype codebase?

  Object.extend(Function.prototype, {
    bind: function(object) {
      var __method = this, __f;
      // Special case: No args or object being bound - just return
this function
      if (arguments.length < 2 && arguments[0] === undefined) return

      if (arguments.length == 1) {
        // Special case: No args are being bound - don't bother
creating a new
        // args structure
        __f = function() {
          return __method.apply(object, arguments);
      } else {
        // General case: Basically do what the native Prototype
        // does, but be as as efficient as possible, and make it
trivial to
        // step through in a debugger.
        var args = $A(arguments), l = args.length-1;
        __f = function() {
          // Set up the args array.  Note that we recycle the args
          // rather than creating a new one.  Also do all this on ONE
line so
          // it only takes one click to step over in a debugger.
          var ll = arguments.length; args.length = l + ll; while
(ll--) args[l+ll] = arguments[ll];
          return __method.apply(object, args);

      // Finally, keep a reference to the original function so we can
      // unbind() (below) as needed.
      __f._boundFunction = this;
      return __f;

    unbind: function() {
      var orig = this;
      while (orig._boundFunction) orig = orig._boundFunction;
      return orig;

You received this message because you are subscribed to the Google Groups 
"Prototype &" group.
To post to this group, send email to
To unsubscribe from this group, send email to
For more options, visit this group at

Reply via email to