Your web browser is outdated, and isn't supported by this website. Read more about upgrading to a modern browser at browsehappy.com.

Overusing anonymous functions

Anonymous functions are commonly used to tidy up callback-heavy JS. They can help reduce visual noise, and allow you to avoid coming up with names for trivial snippets of logic.

// This code filters out the "null" items in a list,
// then multiplies each element by 2.
array
.filter(function notNull(x) {
return x !== null;
})
.map(function double(x) {
return x * 2;
});
// This does the same, but the functions are anonymous
array
.filter(x => x !== null)
.map(x => x * 2);

Anonymous functions are often arrow functions too. Arrow functions themselves aren't necessarily nameless in practice though: most environments these days are clever enough to use the assigned variable name.

// A named arrow function.
// The variable name "double" is used as the function name.
let double = x => x * 2;
console.log(double.name);
Output
"double"

Stack traces

Anonymous functions come with their downsides. Stack traces are easier to read when the functions have names. For example:

const doSomething = () => {
throw new Error("oh no");
};
setTimeout(doSomething);
Output
Error: oh no
    at doSomething (stackTraceExample.js:2)

Note that the function name doSomething helpfully appears in the error output. Without a name, you'd have to rely on other clues, like the filename.

setTimeout(() => {
throw new Error("oh no");
});
Output
Error: oh no
    at stackTraceExample.js:2

Things get especially hairy when lots of files have the same name. Errors become harder to track down than they have to be: this example could be line 12 of any index.js file.

Output
RangeError: invalid array length
    at index.js:12

Faced with any of these stack traces, you'd surely be able to track down the offending code with enough time and patience. But the more clues you leave for yourself, the less stressful that process has to be.

Anonymous React components

Here's another anonymous code pattern you might have seen if you use React.

import React from "react";
export default () => <p>Hello world</p>;

This may look clean, but components declared this way show up as Anonymous or _default in React Dev Tools. That means you can't search for them, and making sense of the tree becomes tricky. Your component tree ends up looking like this...

_default
  _default
    _default
      Anonymous
        ...

...instead of the much more understandable alternative.

Stack
  Box
    Card
      Avatar
        ...

Keep your component tree looking more like the second example by naming your components, and React Dev Tools will be your friend rather than another enemy.

Are anonymous functions always bad then?

Not necessarily. I wouldn't argue against the example up at the top of this post. It's easier to read, not much is likely to go wrong with map(x => x * 2). The downsides to that particular tradeoff aren't that compelling.

Sometimes alternative labels are available for functions beyond their name. For example, many JS testing frameworks encourage code like this:

test("should return true", () => {
assert.equal(doThing(), true);
});

The function itself is anonymous, but the test still has a label that will show up if there's an error.

Anonymous functions are everywhere, and they have their place, for better or worse. But we should be aware of their costs too. We're human, and all but the most trivial functions are subject to bugs. So lean towards using named functions instead when in doubt, and maybe you'll help your future self out.