On the face of it, I like the thought of skipping the arguments prep
in the no-args case, but have you done any profiling to be sure that
it really has a measurable benefit?  Same question on inlining the per-
call arguments concatenation...  Without a solid, measurable benefit,
I'd avoid the additional complexity.  You can deal with the debugger
thing like this:

Replace Prototype's original:

    return __method.apply(object, args.concat($A(arguments)));


    var newargs = args.concat($A(arguments));
    return __method.apply(object, newargs);

Re: unbind.  That version repeatedly unbinds until it finds a non-
bound function, which means it's not the reciprocal of bind.  E.g.:

    x = foo.bind(obj, 1);
    y = x.bind(obj, 2);
    y.unbind() === x ?
    // -> false, the unbind returns foo, not x

>From the name, I'd expect unbind to be the reciprocal of bind.  Since
it's mostly a debug function, it may be worth just using a different

T.J. Crowder
tj / crowder software / com
Independent Software Engineer, consulting services available

On Mar 10, 4:41 pm, Robert Kieffer <bro...@gmail.com> wrote:
> As I suspect is common with many Prototype shops, over here at
> Zenbe.com, 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
> follows:
> - 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
> this;
>       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
> implementation
>         // 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;
>         args.shift();
>         __f = function() {
>           // Set up the args array.  Note that we recycle the args
> array,
>           // 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 & script.aculo.us" group.
To post to this group, send email to prototype-scriptaculous@googlegroups.com
To unsubscribe from this group, send email to 
For more options, visit this group at 

Reply via email to