Traditional versus Arrow functions in JavaScript Classes

What’s up? Oh nothing, just doing `this` and `that`.

Suhan Wijaya
Nov 4 · 4 min read
Image for post
Image for post
Source: Programmer Humor

This is a spiritual sequel to this article.

Create a class with a method using Traditional function like so. Let’s call this Approach A.

Create an instance of that class. When invoking the method on the instance, this refers to the instance. So far, it’s behaving as expected.

But, as soon as we assign the method to a variable and call that function variable, the method loses its context, and you get Uncaught TypeError: Cannot read property ‘someProp’ of undefined.

OK.

Now, let’s create the class with a method using Arrow function like so. Let’s call this Approach B.

This now works.

Why, JavaScript, why?

Image for post
Image for post
Source: Programmer Humor

As per MDN docs, “the class keyword is introduced in ES2015, but is syntactical sugar, JavaScript remains prototype-based.” So if we were to write in pre-ES6 syntax, Approach A looks like this.

The property someMethod is defined on the constructor function’s prototype.

Image for post
Image for post
Chrome Dev Console

But not on the instance.

Image for post
Image for post
Chrome Dev Console

You can access instance.someMethod through prototypal inheritance.

But when you assign instance.someMethod to another variable, the function variable loses its context.

Further, since “code within the class body's syntactic boundary is always executed in strict mode”, this will be undefined instead of defaulting to window or global.

OK.

Now, Approach B looks like this in pre-ES6:

The property someMethod is not defined on the constructor function’s prototype.

Image for post
Image for post
Chrome Dev Console

Instead, it is defined on the instance.

Image for post
Image for post
Chrome Dev Console

Further, an Arrow function is bound to its surrounding lexical context by default (where it physically sits in the code), which seems equivalent to a Traditional function having access to an outer function variable that points to this (i.e., closure).

Hence, even when you assign instance.someMethod to another variable, the function variable remains bound to the instance context.

Note: I’m not 100% sure about the actual ‘under the hood’ mechanism by which Arrow functions derive this, so feel free to comment if you do know.

In any case, I went down this rabbit hole because I’ve been using Arrow functions for writing methods in classical React components, instead of binding Traditional functions (i.e., this.someMethod.bind(this)) in the constructor or when passing it down as prop.

Not endorsing one approach or the other, just describing the difference. Oh, and guess which browser is completely irrelevant to this whole discussion.

📫 Hit me up on LinkedIn or email!

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store