Engineering Journal
Schema Editor
Schema Editor

jQuery $(this) Inside Arrow Functions Fails Silently After a Module Split

2026-06-04

TLDR

A jQuery event handler using $(this) inside an arrow function works in a monolith by coincidence (the outer this happens to have the right data) and fails silently after a module split ($(this) is now the module object, not the clicked element). Convert arrow functions to regular function declarations in any handler where $(this) needs to be the event target.


Symptom

A toolbar button stops working after a refactor. Clicking it fires the event (the handler is attached), but the action does not happen. Adding console.log($(this).data('mode')) prints undefined. The data-mode attribute is on the button element in the HTML.

Why It Happens

Arrow functions in JavaScript do not create their own this binding. They inherit this from the surrounding lexical scope. In jQuery event handlers, the conventional this is the element that received the event. Arrow functions break this convention:

// wrong: arrow function โ€” $(this) is the outer module's this
$('#modeBtn').on('click', () => {
    const mode = $(this).data('mode'); // undefined: 'this' is the module/window
    setMode(mode);
});

// correct: regular function โ€” $(this) is the clicked element $('#modeBtn').on('click', function() { const mode = $(this).data('mode'); // correct: 'this' is #modeBtn setMode(mode); });

In a monolith where the event handler is a method on a module object, this in an arrow function is the module. If the module happened to have a data('mode') equivalent (a property named mode, or a data attribute on the module's root element), the handler appeared to work. After a module split, this in the arrow function is the imported module object, which has no jQuery data() method and certainly no mode data attribute.

The Fix

Search for every jQuery on('event', () => { and check whether the handler body uses $(this). Convert those to regular function declarations:

// find and fix every instance like this
$('[data-action]').on('click', function() {
    const action = $(this).data('action');
    handleAction(action);
});

If you need to reference the outer scope inside the handler (to call a module method), use a closure variable:

const self = this; // capture module reference before the handler
$('[data-action]').on('click', function() {
    const action = $(this).data('action'); // $(this) is the element
    self.handleAction(action);             // self is the module
});

How to Prevent It

Add an ESLint rule: no-invalid-this catches this usage in contexts where it is likely wrong. Alternatively, prefer e.currentTarget over $(this) entirely: $(e.currentTarget).data('mode') works correctly in both arrow functions and regular functions:

$('#modeBtn').on('click', (e) => {
    const mode = $(e.currentTarget).data('mode'); // always the element
    setMode(mode);
});

The Generalizable Lesson

Arrow functions should not be used for jQuery event handlers that need $(this) to refer to the event target. This is not a jQuery quirk. It is how JavaScript this binding works. Arrow functions are correct for handlers that only use the event object (e.preventDefault(), e.target) or only reference outer scope variables.

Read this post in the full Engineering Journal โ†’