Don't use functions as callbacks unless they're designed for it (JavaScript)

in «tip» by Michael Beard
Tags: , , , , , ,

Some really good tips and things to think about in general. Here is a general overview of the article. Read it for the full affect!

From the article:

Watch out for functions being used as callbacks, and objects being used as options, unless they were designed for those purposes. Unfortunately I'm not aware of a linting rule that catches it (edit: looks like there's a rule that catches some cases, thanks James Ross!).

Summary of the problem (which isn't just limited to the example, but some objects as well!):

// Convert some numbers into human-readable strings:
import { toReadableNumber } from 'some-library';
const readableNumbers = someNumbers.map(toReadableNumber);

Here is how the function is declared:

export function toReadableNumber(num) {
  // Return num as string in a human readable form.
  // Eg 10000000 might become '10,000,000'
}

Here's the problem:

// We think of:
const readableNumbers = someNumbers.map(toReadableNumber);
// …as being like:
const readableNumbers = someNumbers.map((n) => toReadableNumber(n));
// …but it's more like:
const readableNumbers = someNumbers.map((item, index, arr) =>
  toReadableNumber(item, index, arr),
);

If the developers of the toReadableNumber function adds a parameter (even if it's defaulted), it still causes issues because

The developers of toReadableNumber felt they were making a backwards-compatible change. They added a new parameter, and gave it a default value. However, they didn't expect that some code would have already been calling the function with three arguments.

so the safe thing to do is create your own function that is designed to work with array.map:

const readableNumbers = someNumbers.map((n) => toReadableNumber(n));

Now, the developers of toReadableNumber can now add parameters without breaking code.

Really should read the article! This takes heavily from the article! The article explains it better. I just wanted to have the gist of it here.