Callbacks - Code Exercises

Callbacks - Code Exercises

Written by David Abram

It's really hard to test your programming knowledge after you have completed a tutorial or a lecture. We have prepared some exercises to help out beginner devs to solidify their understanding of callbacks. Every exercise has a brief description of the problem, starting code, links to relevant MDN docs, and expected results. Try to solve the problems without taking a peek at the solution.

If you need some additional help, you can check out our Functions video from the #lockdown learning series in which we discuss functions and callbacks or contact the author of the article directly.




Callbacks are a critical concept in JavaScript and you won't get very far without knowing how to use them. They are often as confusing to experienced developers as well as to beginners. A callback is nothing more than a function that is passed into another function as an argument to be executed later.

They are so common in JavaScript, you certainly used callbacks without knowing what they were called. You probably wrote a similar snippet multiple times:

const button = document.querySelector("button");

button.addEventListener("click", (e) => {
  this.classList.add("clicked");
});

The second parameter passed into addEventListener is a callback. I have compiled some exercises to improve your understanding of callbacks. Try not to skip them as some code is reused in later exercises.



Contents



Is this number odd?

Write a function that returns true or false for a given number. We will reuse this function, so make it reusable.

Helpful links
Function calls
isOdd(4);
isOdd(5);
Result
false;
true;
Solution(click to show)
const isOdd = (num) => num % 2 === 1;

Exclaim

Write a function that returns the given string with a concatenated exclamation ! at the end. We will reuse this function, so make it reusable.

Helpful links
Function calls
exclaim("Adrian");
exclaim(exclaim("Adrian"));
Result
"Adrian!";
"Adrian!!";
Solution(click to show)
const exclaim = (str) => `${str}!`;

exclaim("Adrian");
exclaim(exclaim("Adrian"));

Double the chars!

Write a function that duplicates each char in a string. If I pass 'abc' to the function, it should return 'aabbcc'. We will reuse this function, so make it reusable.

Helpful links
Function calls
doubleChars("Adrian");
doubleChars("ssssnake");
Result
"AAddrriiaann";
"ssssssssnnaakkee";
Solution(click to show)
const doubleChars = (str) =>
  str
    .split("")
    .map((c) => `${c}${c}`)
    .join("");

doubleChars("Adrian");
doubleChars("ssssnake");

At least two elements

Write a function called atLeastTwo that receives an array and a callback as its arguments. If at least two elements from the array return a truthy value when passed as an argument to the callback, atLeastTwo should return true. If there aren't at least two elements from the array that return a truthy value when passed as arguments to the callback, atLeastTwo should return false.

Helpful links
Function calls
atLeastTwo([1, 2, 3, 4, 5], isOdd);
atLeastTwo([2, 4, 6], isOdd);
atLeastTwo([1, 2, 3, 4, 5], (t) => t > 3);
Result
true;
false;
true;
Solution(click to show)
const isOdd = (num) => {
  return num % 2 === 1;
};

const atLeastTwo = (array, callback) => array.filter(callback).length >= 2;

atLeastTwo([1, 2, 3, 4, 5], isOdd);

atLeastTwo([2, 4, 6], isOdd);

atLeastTwo([1, 2, 3, 4, 5], (t) => t > 3);

Group by

Write a groupBy function that groups elements from an array by the returned value from the callback when an element from the array is passed as an argument.

This is a really common pattern when manipulating arrays.

Helpful links
Function calls
const input = [
  {
    name: "John",
    yearOfBirth: 1988,
    placeOfBirth: "New York",
  },
  {
    name: "Nancy",
    yearOfBirth: 1963,
    placeOfBirth: "New York",
  },
  {
    name: "John",
    yearOfBirth: 1980,
    placeOfBirth: "Toronto",
  },
];

// 1
groupBy(input, (t) => t.name);

// 2
groupBy(input, (t) => isOdd(t.yearOfBirth));
Result
  // 1
  {
    John: [
      {
        name: 'John',
        yearOfBirth: 1988,
        placeOfBirth: 'New York',
      },
      {
        name: 'John',
        yearOfBirth: 1980,
        placeOfBirth: 'Toronto',
      }
    ],
    Nancy: [
      {
        name: 'Nancy',
        yearOfBirth: 1963,
        placeOfBirth: 'New York',
      }
    ]
  }

  // 2
  {
    false: [
      {
        name: 'John',
        yearOfBirth: 1988,
        placeOfBirth: 'New York',
      },
      {
        name: 'John',
        yearOfBirth: 1980,
        placeOfBirth: 'Toronto',
      }
    ],
    true: [
      {
        name: 'Nancy',
        yearOfBirth: 1963,
        placeOfBirth: 'New York',
      }
    ]
  }
Solution(click to show)
const input = [
  {
    name: "John",
    yearOfBirth: 1988,
    placeOfBirth: "New York",
  },
  {
    name: "Nancy",
    yearOfBirth: 1963,
    placeOfBirth: "New York",
  },
  {
    name: "John",
    yearOfBirth: 1980,
    placeOfBirth: "Toronto",
  },
];

const isOdd = (num) => {
  return num % 2 === 1;
};

const groupBy = (array, callback) => {
  array.reduce((accumulator, currentValue) => {
    const key = callback(currentValue);

    if (accumulator[key]) {
      accumulator[key].push(currentValue);
    } else {
      accumulator[key] = [currentValue];
    }

    return accumulator;
  }, {});
};

groupBy(input, (t) => t.name);

groupBy(input, (t) => isOdd(t.yearOfBirth));

Repeat the function x times

Write a repeat function that receives 3 arguments: a string, number of repetitions, and a callback that will be repeated. The repeat function should pass the string to the callback as an argument and repeat the callback x times, with the result of the previous repetition as an argument.

Helpful links
Function calls
repeat("infinite power", 3, exclaim);
repeat("triple", 2, doubleChars);
repeat("trogdor", 3, (t) => `°${t}°`);
Result
"infinite power!!!";
"tttrrriiipppllleee";
"°°°trogdor°°°";
Solution(click to show)
const repeatRecursive = (input, num, callback) => {
  if (num === 0) return input;
  return repeatRecursive(callback(input), num - 1, callback);
};

const repeat = (input, num, callback) => {
  let result = input;
  for (i = 0; i < num; i++) {
    result = callback(result);
  }
  return result;
};

repeat("infinite power", 3, exclaim);
repeat("triple", 2, doubleChars);
repeat("trogdor", 3, (t) => `°${t}°`);