Skip to content

Instantly share code, notes, and snippets.

@jussi-kalliokoski
Created May 18, 2011 10:20
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jussi-kalliokoski/978329 to your computer and use it in GitHub Desktop.
Save jussi-kalliokoski/978329 to your computer and use it in GitHub Desktop.
ES5 Function bind shim
/*
A shim for non ES5 supporting browsers.
Adds function bind to Function prototype, so that you can do partial application.
Works even with the nasty thing, where the first word is the opposite of extranet, the second one is the profession of Columbus, and the version number is 9, flipped 180 degrees.
*/
Function.prototype.bind = Function.prototype.bind || function(to){
// Make an array of our arguments, starting from second argument
var partial = Array.prototype.splice.call(arguments, 1),
// We'll need the original function.
fn = this;
var bound = function (){
// Join the already applied arguments to the now called ones (after converting to an array again).
var args = partial.concat(Array.prototype.splice.call(arguments, 0));
// If not being called as a constructor
if (!(this instanceof bound)){
// return the result of the function called bound to target and partially applied.
return fn.apply(to, args);
}
// If being called as a constructor, apply the function bound to self.
fn.apply(this, args);
}
// Attach the prototype of the function to our newly created function.
bound.prototype = fn.prototype;
return bound;
};
// Or minified... (285 bytes)
Function.prototype.bind=Function.prototype.bind||function(d){var a=Array.prototype.splice.call(arguments,1),c=this;var b=function(){var e=a.concat(Array.prototype.splice.call(arguments,0));if(!(this instanceof b)){return c.apply(d,e)}c.apply(this,e)};b.prototype=c.prototype;return b};
// To try it out, let's make a function called x that logs it's arguments and it's "this" context.
function x(){
console.log(arguments, this);
}
// Then create a bound version of it, called bound, bound to 5 with partially applied arguments 1, 2, 3
var bound = x.bind(5,1,2,3);
// Call it
bound(4); //log: [1, 2, 3, 4] 5
// Now let's try and make a new instance of it
var newBound = new bound(4); //log: [1, 2, 3, 4] Function.bind.bound
// Note that in the native version that would have been [1, 2, 3, 4] x
// But that's not a really useful feature compared to the complexity it requires to be implemented.
// Now let's see if our instanceof operator still works
console.log(newBound instanceof bound); // log: true
console.log(newBound instanceof x); // log: true
// So, yay, it works, have fun!
@collingo
Copy link

Hi,

Just a note to say I had a problem with this script not passing arguments through to the bound function. My testing on IE8 showed that the args array in the bound function was empty. I suspect this is due to caching of the arguments from the parent function (via partial) rather than taking the arguments object from the bound function.

The specific problem for me was when binding to jQuery click handlers which passes through an event object at the time of even. This is coming through as undefined.

Here is an example of what I was trying to do...

function Thing() {
    // blah blah
}
Thing.prototype.handler(e) {
    alert(typeof e); // alerts "undefined"
}
Thing.prototype.bindEvents() {
    $("#button").click(this.handler.bind(this));
}

@jussi-kalliokoski
Copy link
Author

Hi, thanks for trying it out, but yes, it's a bit outdated and inaccurate, I should add a disclaimer that it's not really the best bind shim out there and link to a better one!

@collingo
Copy link

Thanks for getting back to me. Yes this gist is the top hit on Google for "function bind shim" so would be good to recommend an alternative if this isn't being maintained.

I found the example on MDN to work well - https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind#Compatibility

@lokori
Copy link

lokori commented Feb 7, 2016

I just adopted this version for http://www.avoinkoodi.fi to make it work on iPad 1 Safari. There are other things broken, unfortunately, but it's nice to show users at least some content instead of a blank white screen. I have no idea how many people still use the iPad1, but I do personally.

The only "better" alternative I found was the linked version on the Mozilla page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment