Functions vs. Arrow Functions in JavaScript for LWC

Learn when to use traditional functions and arrow functions in JavaScript. See how lexical this helps avoid event handler bugs in Salesforce Lightning Web Components.

An abstract image of a Lightning Web Component showing how let and const variables have clear, block-level scope, while var variables have a less predictable, leaky scope.

Functions are the building blocks of any JavaScript application, and in Lightning Web Components, they’re essential for everything from handling user clicks to processing data. But not all functions are created equal. Modern JavaScript gives us two primary syntaxes: traditional functions and arrow functions. Knowing when to use each is key to writing clean, bug-free LWC.

The Old School: Traditional Functions

You’ve seen these everywhere. The function keyword has been around since the beginning of JavaScript.

// A traditional function declaration
function handleClick(event) {
console.log('Button was clicked!');
}

This syntax is clear. However, the catch is how it handles  the this keyword. In LWC, that can trigger tricky bugs.

The New Way: Arrow Functions

In contrast, ES6 introduced arrow functions (=>). They offer a concise syntax and are often anonymous, assigned to a variable.

// An arrow function expression
const handleClick = (event) => {
console.log('Button was clicked!');
};

Notice it’s shorter. You don’t need the function keyword. For one-liners, drop braces and return.

// A super-concise arrow function
const add = (a, b) => a + b;

However, the real win isn’t the syntax. It’s how arrow functions handle scope.

The Main Event: this and Lexical Scope

First, the key difference: this context.

  • A traditional function gets its own this based on how it’s called. In LWC event handlers, this points to the element that fired the event (for example, lightning-button), not the component. So you can’t access component properties with this.myProperty.
  • An arrow function does not have its own this. Instead, it inherits this from its parent scope. This is called lexical scoping. In an LWC, the parent scope is the component class, so this correctly refers to the component instance.

Let’s see this in action. Imagine you have a component property message you want to update on a button click.

The Problem: Traditional Function in an Event Handler

This code will fail.

// myComponent.js
import { LightningElement, track } from 'lwc';

export default class MyComponent extends LightningElement {
@track message = 'Waiting...';

connectedCallback() {
const button = this.template.querySelector('lightning-button');
// Using a traditional function for the event listener
button.addEventListener('click', function() {
// ❌ MISTAKE: 'this' here is the button element, not the component!
// This line will throw an error because the button has no 'message' property.
this.message = 'Button Clicked!';
});
}
}

Inside that function, this is the lightning-button, so this.message is undefined.

The Solution: Arrow Function to the Rescue

This version works.

// myComponent.js
import { LightningElement, track } from 'lwc';

export default class MyComponent extends LightningElement {
@track message = 'Waiting...';

// In LWC, event handlers in the template are bound correctly by default.
// But for manual listeners like in connectedCallback, arrows are crucial.
connectedCallback() {
const button = this.template.querySelector('lightning-button');
// Using an arrow function for the event listener
button.addEventListener('click', () => {
// ✅ CORRECT: 'this' is inherited from the component class.
// This correctly updates the component's 'message' property.
this.message = 'Button Clicked!';
});
}

// Standard LWC event handling also benefits from arrow function-like behavior
handleRegularClick() {
this.message = 'Regular handler clicked!'; // 'this' is also correct here
}
}

Because the arrow function inherits this from MyComponent, this.message refers to the component’s property as intended.

Decision Flowchart

When you choose between function types in LWC, it usually comes down to this.

Decision flowchart to select between arrow function and function

Takeaway

While traditional functions have their place, arrow functions are the default choice for LWC. Their concise syntax and, more importantly, their lexical handling of this prevent common bugs, especially with event handlers and callbacks. When in doubt, use an arrow function.

Reference:
Read prior articles in this series:

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top