#javascript : Where is this, and what is that ?

AKA : Let’s finally STOP this crazy
that = this thing …


TL; DR

The var that = this; “pattern” on callback function to bypass the loosing this value is a very bad idea.

Use Function.prototype.bind() or, if you’re an old browser, a proxy function like jQuery.proxy().

A history on violence …

Let’s admit it, we’ve all used at least once the var that = this; technique, we even saw some crazyness about this. Let’s (re) define the reason of that non-sense.

Javascript is (theorically…) a mono-thread language, so asynchronous events are handled by “callbacks” :

We can interpret it by “when this thing occurs, run this function”.

Now let’s consider a more complex use of callback inside an object :

As you can see, when we run the timer method, this.property is equal to ‘fooBar’ ; callback method, this.property is now undefined. Why ?

The answer is simple, this is no more what you think ; it’s now the global object (window for browsers, for example). Ok. But then again, why ?

If you ever used Function.prototype.apply to run a closure manually, you’ve seen that its signature is :

func.apply(thisArg [, argsArray])

It can be read as “run this closure with thisArg as the value of this, and argsArray as its arguments”.

So when we run :

setTimeout( this.callback, 1000);

Your Javascript interpreter will wait 1 second before calling :

this.callback.apply( null );

As the spec says : “null and undefined will be replaced with the global object”, it is now clear that this in my callback is now … the global object !

And then … we started using this “design pattern” :

Javascript developers love it and use it widely, very widely. (38,399 occurrences in GitHub at the time of writing this post).

Why is it wrong ?

It is semantically wrong.

English is not my first language, and I can’t say I’m totally fluent in english (you‘ve probably already guessed it, right ?) ; but still, I can understand that this and that is a way to differentiate two distinct thing.

I’m always obsessed about code readability ; and if we’re not talking about esoteric languages like Brainfuck, Ook or Spoon, I consider that a good program is something that you can almost understand when you read it as english.

Here we start with a ambiguous declaration, not the best way to start.

“that” is not reserved or protected.

Ecmascript 5 defined this as a reserved keyword, this means that you cannot create a variable named this nor you can change its value. The following declarations :

var this = { };
this = 90;

will throw a ReferenceError.

that is not a reserved keyword. Not at all. It’s a common variable, and it can be overwritten, edited, deleted, … If we consider the following code :

You can see that we cannot rely on the that variable. Here, we’re loosing one of the benefits of a specified language construct : stability.

And finally, … it’s useless !

And that’s what we’ll see in the next chapter.

How to handle the “I’m losing this” dilemma

Make a proxy function

We’ve seen that the problem is that our setTimeout callback execution can be rewritten as :

callback.apply( null );

Our first solution is to make a “proxy” function that will ensure that the thisArg argument of

func.apply(thisArg [, argsArray])

is set with the correct value :

The myProxy function is basically returning another function that will run the following code :

callback.apply(thisArg, arguments);

By the way, you can see that we have to translate the arguments object to an array by using Array.prototype.slice.call(arguments);

This technique will ensure that callback will be passed the correct arguments.

Remember that this type of proxy function is already implemented in almost every Framework / Library ; for example with jQuery, you can use jQuery.proxy :

$('#myId').on('click', $.proxy(this.onClick, this));

(See source here).

Use the function.prototype.bind method

(NB: If you want an IE8 compatibility, you can’t. But that’s not your worst problem …)

ECMAScript 5.1 (ECMA-262) introduced a new method on the Function object :

func.bind(thisArg[, suppArg1[, suppArg2[, ...]]])

The bind method does the same thing as our previously proxy method, but natively :

$('#myId').on('click', this.onClick.bind(this));
setTimeout( (function() { console.log(this); }).bind({}), 1000 );
// -> { }

Buy a Delorean and go to the future

ECMAScript 6 introduced a new feature : Arrow functions.

Arrow functions offers a syntax improvement (I’ll cover it one day) that we’ll skip here, but another noticeable feature is that Arrrow function keeps the this value unchanged :

(You can try it in latest Firefox)

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.