Skip to content

Instantly share code, notes, and snippets.

@sranso
Last active August 29, 2015 14:04
Show Gist options
  • Save sranso/20fb2162d6c1748dca85 to your computer and use it in GitHub Desktop.
Save sranso/20fb2162d6c1748dca85 to your computer and use it in GitHub Desktop.

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 foos 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:

  1. Bind takes a function (fn), a context, and some arguments (args).
  2. argsArr takes just the arguments of that function by removing the funciton and the context (because those aren't arguments).
  3. Next it returns the fn that was passed in,
  4. with the given context specified in the bind call, and any given arguments.
  5. The end of the function.
  6. 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

@cassidoo
Copy link

The line In the example above, bind allows the function inside of foos ... should have an apostrophe so it's foo's!

@Whitespace
Copy link

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 to window – not what we were expecting!"

@Whitespace
Copy link

When you're going line-by-line, break it up with bullets and embed a gist with line numbers. Then you can ignore the closing brace lines and only explain the juicy bits.

@Whitespace
Copy link

In paragraph 2 the last sentence seems to have been messed up:

"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."

😖

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