Team Shabu, AKA the web team, works almost entirely in Javascript. One function we use often is bind
. Let's take a little lookskis at what's going on here.
Here's a simple example of how you might use bind
:
var obj = {
foo: function() {
console.log(this);
this.name = 'baz';
(function() {
console.log('inside func');
console.log(this.name);
}.bind(this))();
}
}
obj.foo();
// Object {foo: function}
// inside func
// baz
In the example above, bind
allows the function inside of foo
s outer function to have access to this.name. If we did not bind
then this.name
would return undefined
. And it would do so because this
now refers to what is one step No good if we want to be able to work with the same this
in a nested function.
So what is going on behind the scenes with bind
? What's this sneaky guy doing? Well, bind
returns a function with new or added context, optionally adding any additional supplied parameters to the beginning of the arguments collection. Let's take a look at a rewrite below.
function bind(fn, context, args) {
var argsArr = slice(arguments, 2); //curried args
return function() {
return fn.apply(context, argsArr.concat(slice(arguments)));
};
}
So, line-by-line, let's go through it:
- Bind takes a function (
fn
), acontext
, and some arguments (args
). argsArr
takes just the arguments of that function by removing the funciton and the context (because those aren't arguments).- Next it returns the
fn
that was passed in, - with the given
context
specified in the bind call, and any given arguments. - The end of the function.
- The end of the other function. Bind returns a function that will execute in a given context.
To really hammer it home, let's take a look at an instance where we do not use bind
:
$('.gist-author img').click(function() { // my avatar image on gist.github.com :-P
console.log(this);
(function() {
console.log('inside');
console.log(this);
})();
});
// if you click that image, you'll get the following...
// <img src="https://avatars1.githubusercontent.com/u/4968408?s=140" width="26" height="26">
// inside
// Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
Yikes. If we want to perform a function on the original this
-- in this case, img
-- we can't. Inside the inner function, this
refers to the window
because this
defaults to window
when inside a jQuery function. This is the problem that bind
tries to solve: to allow us to be specific with our context.
Awesome. I hope that's helpful. It certainly helps us at Venmo.
Until next time,
Sarah Ransohoff
You should preface it all by saying bind is a function in the standard library, and link to it: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
In the last paragraph, I'd say something like, "Let's hammer it home by looking at some jQuery code that doesn't use bind … since we're using jQuery in this example,
this
defaults towindow
– not what we were expecting!"