Today, I want to share a trick I learned in the MDN Web Docs that helps prevent leaking arrow functions. Let's dig in!

In vanilla JS, if a function doesn't explicitly return a value, its return value is undefined.

The following function logs the string "Hello!" to the console, but because it doesn't explicitly return a value, its return value is undefined:

function sayHello() {
console.log("Hello!");
}

sayHello(); // undefined

Let's rewrite the sayHello() function using an arrow function. It still doesn't explicitly return a value, so its return value is still undefined:

const sayHello = () => {
console.log("Hello!");
};

Perhaps we might decide to make our sayHello() function more compact? Let's put it on a single line:

const sayHello = () => console.log("Hello!");

This change might seem inconsequential, but it isn't! When you omit the curly braces ({}) from an arrow function, its return statement becomes implicit. This means that our sayHello() function now returns the return value of the console.log() method. It's equivalent to the following:

const sayHello = () => {
return console.log("Hello!");
};

It relies on the console.log() method's return value being undefined.

What if the console.log() method changes? For argument's sake, what if it returns true in a future version of the ECMAScript specification? Then our sayHello() function will also return true.

To prevent the behaviour of our sayHello() function from changing, we can prepend its return value with the void operator:

const sayHello = () => void console.log("Hello!");

As the MDN Web Docs explain, The void operator evaluates the given expression and then returns undefined. As such, even if the return value of the console.log() method changes, our sayHello() function will always return undefined.