contact us

Use the form on the right to contact us.

You can edit the text in this area, and change where the contact form on the right submits to, by entering edit mode using the modes on the bottom right.


San Francisco, CA, 94160
United States

Writing

Why I Hate `var self`

Jesse Atkinson

I hate var self. I hate it. I hate it and its sister var that. Let's not even speak of the black sheep of the family, var _this — lest we wish to conjur up other barbaric practices conducted by lesser JavaScript developers.

No no no. var self is for the weak. The unsure. The impotent. The wallflower shoegazers of the JavaScript world who are too scared to ask their code for a bloody dance.

"Why do you hate this thing that seems to permiate many JavaScript libraries penned by competent and skilled devs. Devs more skilled than you even!"

I'm glad you asked.

I hate var self because var self represents failure. A failure to use what the language has given you and intended for you to do. JavaScript gives you this. And this, as you well know, represents... well... this. The thing you're currently acting upon. When you assign this to a variable and then reference that variable in some scope below you are admitting all devs who will interact with this code in the future and yourself that you failed. You failed to give this thought. You've failed to leverage the tools JavaScript has so graciously provided you. Of course I'm talking about .bind and its cousins .apply and .call.

Let's go over an example. Here's a bit of code that leverages that. I'll assume we have access to jQuery, but this applies to even without. (Lets pretend, for example's sake, that we are doing somethign more complex with data here than simply passing it to doSomethingWithTheData. Otherwise we could pass doSomethingWithTheData as the callback function for done.)

var that = this;

$.ajax({
  type: 'GET',
  url: '/api/v1/auth/user/current/',
  contentType: 'application/json'
}).done(function (data) {
  that.doSomethingWithTheData(data);
});

Now lets rewrite this so that we do not have to store this in a variable using bind.

$.ajax({
  type: 'GET',
  url: '/api/v1/auth/user/current/',
  contentType: 'application/json'
}).done(function (data) {
  this.doSomethingWithTheData(data);
}.bind(this));

Lets make this even better. We'll assign the callback method to a named variable and bind the callback method to this. Finally we'll change that verbose $.ajax into the shorthand jQuery method for specifically fetching JSON.

var onDone = function (data) {
  this.doSomethingWithTheData(data);
};

$.getJSON('/api/v1/auth/user/current/').done(onDone.bind(this));

"But Jesse, I'm not familiar with bind. What browsers support bind?"

I'm glad you asked. IE9+ as well as any remotely modern version of Chrome, Firefox, and Safari. (See this link).

"Okay. Fine. But this is a seriously trivial discussion. Why do you care?"

That's a fair question. I will admit that it is trivial in the grand scheme of things. If you tell your manager you'd like to take next sprint to change all variable assignments of this they would rightly look at you like you were insane. However, when building a product part of building it is building it well. You can choose to ignore this advice. You can also write your entire app with mixed line endings, no whitespace, no comments, and bind every object to the global window. But chances are if you're still reading this it's because you care. You care about not only your product working but the code that you write to create your product being readable and maintainable, especially for other coders. My argument against var self stems from my hatred of confusion and discord and my love of legibility and clarity.

P.S. Ever have trouble remembering the difference between .call and .apply? Here's an easy way to remember. .call begins with the letter "c". You pass in all of the parameters to the method you invoke with .call using commas to seperate the params. I.E. foo.call(this, bar, baz, bing);. .apply begins with the "a". You pass in all of the parameters to the method you invoke with .apply using an array. I.E. foo.apply(this, [bar, baz, bing]);.