Mockability

If you want to mock or spy on a class method, the easiest and proper way to do so is with the prototype as all changes to the Object prototype object are seen by all objects through prototype chaining.

Let’s say we want to do some tests with our previous class A .

A.prototype.handleLongClick is defined.

A.prototype.handleClick is not a function.

Oops, since we used an arrow function in a class property our function handleClick is only defined on the initialization by the constructor and not in the prototype. So, even if we mock our function in the instantiated object, the changes won’t be seen by other objects through prototype chaining.

Inheritance

Let’s define our base class A .

If class B inherit from class A , handleClick won’t be in the prototype and we can’t call super.handleClick from our arrow function handleClick .

If class C inherit of class A , but implement handleClick as a function instead of an arrow function, handleClick will only executes super.handleClick() and nothing else. Strange isn’t?

It’s because the instantiation of handleClick in the constructor of our parent class overrides it.

C.prototype.handleClick() will call our implementation but will fail with the previous error: Uncaught TypeError: (intermediate value).handleClick is not a function .

If class D is a plain class that inherit from class A , he will have an empty prototype and new D().handleClick() will log A.handleClick .

Performance

Now the interesting part, let’s talk about performance.

We know that usual functions are defined in the prototype and will be shared across all instances. If we have a list of N components, these components will share the same method. So, if our components get clicked we still call our method N times, but it will call the same prototype. As we’re calling the same method multiple times across the prototype, the JavaScript engine can optimize it.

On the other hand, for the arrow functions in class properties, if we’re creating N components, these N components will also create N functions. Remember what we’ve seen in the transpiled version, class properties are initialized in the constructor. Which means if we click on N components, N different functions will be called.

Let’s see how they are doing in a benchmark with V8 engine (Chrome).

The first one is simple, we only measure the instantiation time, and we call our method one time.

Beware that number doesn’t really matter in this one, since one instantiation won’t be noticed in your application and we’re talking about operations per second and the number are high enough. I’m more concerned by the gap between our functions.

For the second one, I used a representative use case. The instantiation of 100 components — like a list — which after we called the method one time on each.

All benchmarks were run on a MacBook Pro 13" 2016 2GHz on Mac OS X 10.13.1 and Chrome 62.0.3202.

In short, to improve performance, you should declare your shared method in the prototype and only bound it to the context if you need to (if you pass it as prop or callback). It makes sense to bound our shared methods to the prototype and initialized our properties in the constructor of each instance, but methods not much.

We’re still talking about high ops/s, but we clearly see that arrow functions in class properties are not as performant as we thought.

And yes you’re right, the usage of property initializers won’t be noticed in our applications unless we instantiate many components. Yes we can see this as a premature optimization and you’re right premature optimizations are the root of all evil — with E Corp — but instead, can we see arrow functions in class properties as premature feature or misused feature? Hopefully, engines will optimizes the arrow functions in class properties.

P.S: Class properties for properties are such a great improvement!

I’ve seen this in many application and libraries, even ones that contain components we can instantiate multiple times. Should we really use this ESnext feature for class methods in our packages knowing that can impact — for the moment — our performance?

Personally, I don’t think that arrow functions in class properties are convenient enough — in some cases — at the expense of the performance.