The End of “var that = this” – Arrow Functions in ECMAScript 6 Are Awesome

JavaScript has taken off. If you are a web developer, you have probably noticed the trend. In the last couple of years the language has seen a tremendous growth in adoption and tools. The community has created some awesome things, among which are client MV* frameworks like Backbone and AngularJS, and also server tools like node.js. The future seems bright for JavaScript and if you are just starting to learn web development, make sure that you pay attention.

I was looking through the new stuff introduced in the latest specification for ECMAScript 6, which is the official standardized name for JavaScript. This new specification is still in development and there’s no browser support yet, but it introduces some very interesting changes. Today I want to focus on only one of them, namely – arrow functions. Arrow functions is a new syntax for declaring functions in JavaScript, but not only that. It also redefines the meaning of this . We will see why this is so good in a moment, but first let’s talk about the syntax.

Arrow Function Syntax

A normal JS function is declared like this:

In arrow function syntax, the same code can be translated as follows:

As you have already guessed from the above example, arrow functions start with the list of parameters in brackets, followed by a double arrow (=>), and then an expression which returns the value of the function. In the above case the function multiplies the two parameters passed to it. However, you are not limited to only using a single statement. You can also write a function which executes multiple statements, as long as it returns only one value. In that case, we need to enclose the multiple statements in brackets.

You may be thinking that this is not much different from the regular function syntax and it doesn’t help you a lot. Well, if you have very simple functions with only 1 parameter and a single return statement, things look much simpler.

As you can see, we have omitted the braces which enclose the parameter list, as well as the curly brackets enclosing the statements. When there’s just one function parameter and one return statement, they are optional. This saves a lot of writing. But the biggest advantage it gives over regular function syntax is how it redefines the meaning of the  this keyword.

The meaning of “this”

When you use the this keyword inside a JavaScript function, its value depends on how the function was called, unlike other object-oriented languages where this always points to the current object instance. In a global function, this refers to the window object:

When your function is a member of an object, then this points to the object itself.

If the function handles some DOM event in the web page, then this points to the DOM element which triggered the event.

For more info on the different behavior of  this , you can read this great article on MDN: this

Of course today most developers are not writing event handlers and global functions like the above examples. People have started using the module pattern to introduce better structure to their applications. They are using immediately invoked function expressions and use the concept of closures to emulate encapsulation in JavaScript objects and block access to some of the members. If you are not using these, you should be.

Note: If you are not familiar with the module pattern and closures, please go ahead and read about those first. These articles are a good starting point:

In order to illustrate how arrow functions change the meaning of this, let’s take a simple module as an example.

The above code snippet defines a single module. Note the difference between writing public and private methods. Private methods are normal functions inside our module and can only be accessed by other functions inside the same scope. Public methods are members of a custom object. We return that custom object as the result of our immediately executed function. So anyone outside our module will only see the members of this object.

When we log the value of this in a private method, it points to the object which called the function. Why is this so?

The reason is that privateMethod is not a member, it is a normal function defined in our module’s scope. Inside that function, this points to the caller, in this case window  (see the examples above).

For object-oriented development, it is very weird for this to point to an external caller. That’s why JS developers have tried to escape from this oddity using different techniques. One such technique was to declare an internal variable, which holds a reference to this even after the closure exits. You can declare such a variable right next to our private method.

This practice is very common and widespread. Once we have an internal variable, we use that variable in all our methods instead of  this . We guarantee that it will point to the object it is declared in. Although this solves the problem, it is not very straightforward and may still confuse developers who are new to the concept.

Other techniques to solve the same problem are to use bind(), call() or apply() to change the value of this when you invoke each function. However, this moves the responsibility of supplying the scope to the caller and is not very good for encapsulation.

Arrow functions to the rescue

Designers of the JavaScript language and members of the committee working on the ECMAScript specification have noticed this problem, and they have provided a solution in the form of arrow functions. Arrow functions capture the value of this  from the enclosing context, no matter the caller. This changes everything (no pun intended). If we use arrow functions, we can just use this everywhere and our code will work.

No matter who calls the method, it will always log the Module object return value to the console. You can see that this feels much more intuitive than introducing variables to hold our context. Arrow functions can change the way we currently write JavaScript modules. The specification is not finalized yet, and currently there is no official support in any browser, but very soon you will be able to play with the new ECMAScript 6 features and take advantage of the new syntax.

You can follow how browser support for the different features of ES6 rolls out at this excellent comparison table: http://kangax.github.io/es5-compat-table/es6/

  • Karel Novak

    Hello,

    privateMethod(() => console.log(this)); calls privateMethod with () => console.log(this) as an argument. If you want to define that method you should write var privateMethod = () => console.log(this); . I am not sure if it is a mistake or your intention. The privateMethod definition is missing there anyway. Thank you for writing about this nice new feature.

    Karel