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();
}
}