ES6 Arrow function is one of my favourite ES6 features. Its lexical this makes most sense in most cases.
The Problem:
However, I came a cross a case today where ES6 Arrow functions cause a bug when used as a JQuery callback. The code started like this:
$(document).on('blur', 'input[type=text]', function () { const $elem = $(this); if ($elem.val().length === 0) { // do something } });
My ESLint config did not like the anonymous function so I changed it to arrow function:
$(document).on('blur', 'input[type=text]', () => { const $elem = $(this); if ($elem.val().length === 0) { // do something } });
It looked all good and it passed all checks. But when a text input triggered a blur
event, an error occurred complaining about $elem.val()
is null
.
I then put a breakpoint at the const
line and inspected it in Chrome’s console. The $(this)
still evaluated as an array of input elements (with one item) but strangely, once assigned, the $elem
became something else (jquery.fn.init {}
) and the $elem.val()
evaluated null
.
Ok, with ES6 arrow function’s Lexical This, it kind-of make sense. The lexical this in the example is actually not a Input element, it is pre-bound to the lexical this
when the event handler is registered. Indeed, it is undefined
if I put a console.log(this)
there. In this case, arrow function should be avoided because lexical this is not desirable.
But how do we explain the results I had when inspecting with Chrome console ? It turned out that Chrome inspector is no good at resolving this
with the arrow function and keep reporting as if it is a normal callback function.
Conclusion:
- Take extra care when using ES6 arrow function when non-lexical
this
is desirable. - Chrome browser inspector is not good at reporting Lexical This.