A JavaScript utility function is a modular and reusable piece of code that performs a specific task related to general programming needs. It is designed to make complex operations simpler and more concise, as well as to improve code readability and maintainability.
A utility function should:
- Have two or fewer arguments for easier testing 1
- Do one thing to make it easier to read, refactor, and test.2
- Have a name that clearly states what it does. For example, the function name randomInt implies that it returns a random number, instead of random which could mean a random object, array, integer, boolean, etc.3
Other developers might set them up differently, but I put all my utility functions for a project in one file (usually in /src/utility/utility.js).
The file looks something similar to this:
function a() {
// function a code
}
function b() {
// function b code
}
function c() {
// function c code
}
const utilityService = { a, b, c };
export default utilityService;
// Don't forget the End of File extra lineSplits an array into smaller arrays of a specified size.
function chunk(arr, size) {
  let result = [];
  for(let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }
  return result;
}Flattens an array of arrays into a single array.
function flatten(arr) {
  return arr.reduce((acc, val) => {
    Array.isArray(val) ? Array.prototype.push.apply(acc, val) : acc.push(val);
    return acc;
  }, []);
}Removes falsy values from an array.
function compact(arr) {
  return arr.filter(Boolean);
}Returns the difference between two arrays.
function difference(arr1, arr2) {
  return arr1.filter((val) => !arr2.includes(val));
}Returns the intersection of two arrays.
function intersection(arr1, arr2) {
  return arr1.filter((val) => arr2.includes(val));
}function base64UrlDecode(base64Url) {
  let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  let jsonPayload = decodeURIComponent(
    window.atob(base64)
      .split('')
      .map(c => `%${c.charCodeAt(0).toString(16).padStart(2, '0')}`)
      .join('')
  );
  return JSON.parse(jsonPayload);
}
Returns object from encoded jwt token
function parseJwt(token) {
  if (!token) {
    return {};
  }
  let base64Url = token.split('.')[1];
  return base64UrlDecode(base64Url);
}Returns a new object with only the specified properties.
function pick(obj, keys) {
  return keys.reduce((acc, key) => {
    if (obj.hasOwnProperty(key)) {
      acc[key] = obj[key];
    }
    return acc;
  }, {});
}Returns a new object with the specified properties removed.
function omit(obj, keys) {
  return Object.keys(obj)
    .filter((key) => !keys.includes(key))
    .reduce((acc, key) => {
      acc[key] = obj[key];
      return acc;
    }, {});
}Checks if two objects are equal.
function isEqual(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}Checks if an object is empty.
function isEmpty(obj) {
  return Object.keys(obj).length === 0;
}Returns a deep copy of an object.
function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}Capitalizes the first letter of a string.
function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}Truncates a string to a specified length and adds an ellipsis if it exceeds that length.
function truncate(str, len) {
  return str.length > len ? str.slice(0, len) + '...' : str;
}Removes HTML tags from a string.
function stripTags(str) {
  return str.replace(/<[^>]*>?/gm, '');
}Converts a string to a slug.
function slugify(str) {
  return str
    .toLowerCase()
    .replace(/[^a-zA-Z0-9]+/g, '-')
    .replace(/(^-|-$)+/g, '');
}Reverses a string.
function reverse(str) {
  return str.split('').reverse().join('');
}Rounds a number to a specified number of decimal places.
function round(num, places) {
  return +(Math.round(num + 'e+' + places) + 'e-' + places);
}Generates a random integer between two numbers.
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}Calculates the factorial of a number.
function factorial(num) {
  if (num < 0) return undefined;
  if (num === 0) return 1;
  return num * factorial(num - 1);
}Generates the nth number in the Fibonacci sequence.
function fibonacci(n) {
  if (n < 1) return 0;
  if (n <= 2) return 1;
  let prev = 1,
    curr = 1;
  for (let i = 3; i <= n; i++) {
    let next = prev + curr;
    prev = curr;
    curr = next;
  }
  return curr;
}Generates the fibonacci sequence and stopping at a specific number.
function fibonacciSequence(num) {
	const sequence = [0, 1];
	let i = 2;
		
	while (sequence[i - 1] + sequence[i - 2] <= num) {
		sequence[i] = sequence[i - 1] + sequence[i - 2];
		i++;
	}
	return sequence;
}Checks if a number is prime.
function isPrime(num) {
  if (num <= 1) return false;
  for (let i = 2; i <= Math.sqrt(num); i++) {
    if (num % i === 0) return false;
  }
  return true;
}Formats a date as a string.
function formatDate(date) {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = ('0' + (d.getMonth() + 1)).slice(-2);
  const day = ('0' + d.getDate()).slice(-2);
  return `${year}-${month}-${day}`;
}Checks if a year is a leap year.
function isLeapYear(year) {
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}Calculates the number of days between two dates.
function daysBetween(date1, date2) {
  const oneDay = 24 * 60 * 60 * 1000;
  const d1 = new Date(date1);
  const d2 = new Date(date2);
  return Math.round(Math.abs((d1 - d2) / oneDay));
}Calculates a person's age based on their birthdate.
function age(date) {
  const d = new Date(date);
  const diff = Date.now() - d.getTime();
  const ageDate = new Date(diff);
  return Math.abs(ageDate.getUTCFullYear() - 1970);
}Calculates the day of the year for a given date.
function dayOfYear(date) {
  const d = new Date(date);
  const start = new Date(d.getFullYear(), 0, 0);
  const diff = d - start;
  const oneDay = 1000 * 60 * 60 * 24;
  return Math.floor(diff / oneDay);
}Limits the rate at which a function can be called.
function debounce(func, wait) {
  let timeout;
  return function (...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
}Limits the frequency at which a function can be called.
function throttle(func, limit) {
  let inThrottle;
  return function (...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}Creates a deep clone of an object.
function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}Shuffles the elements of an array.
function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}Flattens a nested array.
function flat(array) {
  return array.reduce(
    (acc, curr) =>
      Array.isArray(curr) ? acc.concat(flat(curr)) : acc.concat(curr),
    []
  );
}Adds an outline to a parent element if the child element has focus
function addOutlineOnFocus = (focusElem, parentElem) => {
  focusElem?.addEventListener("focusin", () => {
    if (focusElem?.matches(":focus-visible")) {
      parentElem?.classList?.add("tab-form-outline");
    }
  });
  focusElem?.addEventListener("focusout", () => {
    parentElem?.classList?.remove("tab-form-outline");
  });
};Creates a browser cookie with the inputted key and value
function createCookie(key, value) {
  let date = new Date();
  date.setMonth(date.getMonth() + 12);
  document.cookie = `${key}=${value};expires=${date};`;
}Gets the value of an existing cookie based on the name
function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) {
    return parts.pop().split(';').shift();
  }
}