Skip to content

Instantly share code, notes, and snippets.

@jashmenn
Last active September 6, 2022 23:11
Show Gist options
  • Save jashmenn/b306add36d3e6f0f6483 to your computer and use it in GitHub Desktop.
Save jashmenn/b306add36d3e6f0f6483 to your computer and use it in GitHub Desktop.
Javascript var self = this; vs. .bind

The Problem

In Javascript this is bound in unexpected ways. Functions, in particular, create a new 'this' and so when you want to keep a reference to an "outer" object you sometimes see the pattern:

var self = this;

as in:

var self = this;
return function(whatever) {
  return self.foo(whatever); // `this` here is for the inner function
}

Is this a good pattern? Shouldn't we just use .bind(this) on the inner function?

Sources Say:

I've done some reasearch and here are a few links that discuss this idea along with a little summary of what they suggest.

Summary

To me, it seems that .bind definitely has it's place. For instance when you have a function in a variable and you want to attach it to a particular this.

That said, in the case of nested anonymous functions I think that using var self = this; is straightforward and requires less mental accounting vs. using .bind. For example, say we have two nested functions:

function foo() {
  return (function() {
    doSomething((function() {
      return this.name; // what is `this` again?
    }).bind(this));
  }).bind(this);
}

vs.

function foo() {
  var self = this;
  return (function() {
    doSomething((function() {
      return self.name; // `self` is easy to know because its defined 
    })
  })
}

Of course, because this is a matter of style the issue of "mental accounting" will differ from person to person. But to me, given the semtanics of Javascript's this, I think that self = this is easy to comprehend when you have nested callbacks.

See Also

@msieurtoph
Copy link

msieurtoph commented Feb 1, 2017

Refering to this jsperf : https://jsperf.com/bind-vs-self-closure
It looks like var self = this; is a lot more faster than the .bind(this).

@aturner-andplus
Copy link

You're missing a closing parenthesis on the self reference example. 😛

@Pictor13
Copy link

Pictor13 commented Jun 7, 2022

IMHO, being explicit using bind() is more understandable than a more-cryptic & non-standard context = this, with context often varying among self, that, thisArg, context, 'ctx'.

The reassignment as variable doesn't express a clear intention, because its reason to be lies in an implicit implementation detail (as it often happens in Javascript 😓): the closure.
New JS devs aren't necessarily aware of closures and about the self = this idiom.
They might not be aware of what .bind does too; but they can copy-paste & find a more straightforward MDN documentation for it.

Specifically, .binding a function makes it clear:

  • that the intention/verb is to provide a context
  • what is the subjected function
  • what is the context object provided

In this, bind is unbeatable for clarity and code sharing. Also it is more straightforward to trace, debug & refactor, for developers of any level of experience.
I tend to prefer it as a habit, even when it's inconvenient, because it feels cleaner, more structured, and less obscure.

Only case where I might use var self = this is when I need multiple contexts inside a callback; but in most of my use-cases I tend to resolve that by accessing event.target as second context, and still keep this bound via .bind, without having to get anything from the outer scope.

Example

function Page() {
  this.body = document.querySelector('body')
  this.btn = document.createElement('button')
  this.btn.textContent = 'click me!'
  this.btn.addEventListener('click', this.onClick.bind(this))
  this.body.append(this.btn)
}
Page.prototype.onClick = function(event) {
  var button = event.target
  var page = this

  button.textContent = 'clicked!'
  page.changeBackground()
}
Page.prototype.changeBackground = function() { this.body.style.backgroundColor = 'lightblue' }

Of course the choice depends also on how the script code is being structured.

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