DEV Community

Cover image for 10 Helpful JavaScript Utility Functions
Technophile
Technophile

Posted on

10 Helpful JavaScript Utility Functions

Hey, there! 👋

Today, we'll cover 10 custom utility functions in JavaScript that can come in handy in most of your projects.

Table of Contents


01. `console.log()`

Yes, the tool we all love and use for printing, debugging, etc. So, why not shorten it to reduce typing and save some time?

const { log } = console;

log("Hello world!");
// Expected output: Hello world!

// SAME AS //

console.log("Hello world!");
// Expected output: Hello world!
Enter fullscreen mode Exit fullscreen mode

Explanation: we use the destructuring assignment to be able to extract the log method from the console.


02. `querySelector()`

When working with JavaScript, you might have heard the term DOM Manipulation and used getElementById(), querySelector() and other methods to access the DOM elements. So, let's make it easier to work with.

const select = (selector, scope = document) => {
  return scope.querySelector(selector);
};

const title = select("h1");
const className = select(".class");
const message = select("#message", formElem);

// SAME AS //

const title = document.querySelector("h1");
const className = document.querySelector(".class");
const message = formElem.querySelector("#message");
Enter fullscreen mode Exit fullscreen mode

Explanation: We're passing 2 parameters in the select() function:

  • 1st: DOM element you want to select
  • 2nd: Scope from which you access that element (default = document);

03. `addEventListener()`

Handling the click, mousemove and other events are mostly implemented with the addEventListener() method.

const listen = (target, event, callback, ...options) => {
  return target.addEventListener(event, callback, ...options);
};

listen(buttonElem, "click", () => console.log("Clicked!"));

listen(document, "mouseover", () => console.log("Mouse over!"));

listen(formElem, "submit", () => {
    console.log("Form submitted!");
  }, { once: true }
);
Enter fullscreen mode Exit fullscreen mode

Explanation: We're passing 4 parameters in the listen() function:

  • 1st: Element you want to target (e.g. 'window', 'document' or specific DOM element)
  • 2nd: Event type (e.g. 'click', 'submit', 'DOMContentLoaded', etc.)
  • 3rd: Callback function
  • 4th: Remaining optional options (e.g. 'capture', 'once', etc.). Also, we use the spread syntax to allow for other options if necessary. Otherwise, it can be omitted just like in the addEventListener method.

04. `random()`

You might probably be aware of Math.random() function that generates random numbers from 0 to 1. You might also know about other hacks, like Math.random() * 10, which should now generate random numbers from 0 to 10. However, the problem is that despite knowing the limit, we don't have much control over the minimum value.

const random = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1)) + min;
};

random(5, 10);
// 7
Enter fullscreen mode Exit fullscreen mode

Explanation: Here's the better explanation by MDN Docs


05. `times()`

Sometimes, we often find ourselves in need of running a particular function several times.

Of course, we can use setInterval() to run every interval amount of time like this:

setInterval(() => {
  randomFunction();
}, 5000); // runs every 5 seconds
Enter fullscreen mode Exit fullscreen mode

The problem is that we aren't able to specify how many times we want to run it. So, let's fix it!

const times = (func, n) => {
  Array.from(Array(n)).forEach(() => {
    func();
  });
};

times(() => {
  randomFunction();
}, 3); // runs 3 times
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Array(n) - creates a new array with the length of n.
Array(5); // => [,,]
Enter fullscreen mode Exit fullscreen mode
  • Array.from() - creates a shallow copy from Array(n). It helps us to make an array to be usable, filling it with 'undefined'. You can also use the Array.prototype.fill() method to achieve the same result.
Array.from(Array(3)); // => [undefined,undefined,undefined]
Enter fullscreen mode Exit fullscreen mode

Note: While researching this utility function, I realized that some programmers prefer to put the n parameter first and then the function times(n, func). But, it looked kinda weird to me, so I decided to swap their places, thus making the syntax more similar to the setInterval() function:

setInterval(func, delay);

times(func, n);
Enter fullscreen mode Exit fullscreen mode

Also, you call it setTimes() instead of times() to match with the setInterval() and setTimeout() methods depending on your preferences.


06. `slugify()`

Have you ever found yourself in need of turning the title of your blog articles into a 'URL-like' format?

JS Utility Functions => js-utility-functions
Enter fullscreen mode Exit fullscreen mode

Here is a little utility function that does so:

const slugify = (string, separator = "-") => {
  return string
    .toString() // Cast to string (optional)
    .toLowerCase() // Convert the string to lowercase letters
    .trim() // Remove whitespace from both sides of a string (optional)
    .replace(/\s+/g, separator) // Replace spaces with -
    .replace(/[^\w\-]+/g, "") // Remove all non-word chars
    .replace(/\_/g, separator) // Replace _ with -
    .replace(/\-\-+/g, separator) // Replace multiple - with single -
    .replace(/\-$/g, ""); // Remove trailing -
};

slugify("Hello, World!");
// Expected output: "hello-world"

slugify("Hello, Universe!", "_");
// Expected output: "hello_universe"
Enter fullscreen mode Exit fullscreen mode

Explanation: Here is the discussion by the GitHub community


07. `validateEmail()`

When working on small projects and trying out email validation for your form, you can use this super simple method to achieve your goal. Also, it can be very handy for small tests.

const validateEmail = (email) => {
  const regex = /^\S+@\S+\.\S+$/;
  return regex.test(email);
};

validateEmail("youremail@org.com"); // true
validateEmail("youremail@com"); // false
validateEmail("youremail.org@com"); // false
Enter fullscreen mode Exit fullscreen mode

Explanation: You can play around with the regex here.

  • RegExp.test() searches if the provided regex expression matches with the string

Note: For larger projects, I would recommend using libraries like validator.js to handle heavy lifting for you.


08. `capitalize()`

We have built-in toUpperCase() and toLowerCase() methods in JavaScript. However, we don't have built-in support for capitalization. So, let's build one!

const capitalize = (str) => {
  const arr = str.trim().toLowerCase().split(" ");

  for (let i = 0; i < arr.length; i++) {
    arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
  }

  return arr.join(" ");
};

capitalize("hello, world!");
// Expected output: "Hello, World!"
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • split() - turns the string into an array
  • arr[i].charAt(0).toUpperCase() - upper cases the 1st letter of each word
  • arr[i].slice(1) - returns the remaining word letters.
  • arr.join(" ") - turns the array back into string

09. `sanitizeHTML()`

Ever heard of Cross-site scripting (XSS) attacks? If not, it's a type of attack that occurs on most websites. For example, when submitting a form, an attacker might try to send malicious scripts to break into the system. To prevent this from happening on your forms, you can use this handy function that will "sanitize" the script code.

const sanitizeHTML = (str) => {
  const div = document.createElement("div");
  div.textContent = str;
  return div.innerHTML;
};

sanitizeHTML("<h1>Hello, World!</h1>");
// Expected output: "&lt;h1&gt;Hello, World!&lt;/h1&gt;"
Enter fullscreen mode Exit fullscreen mode

Explanation: Unlike innerHTML, textContent does not parse the string as HTML, while innerText only shows "human-readable" elements.

Moreover, using textContent can prevent XSS attacks. - MDN Docs

Sanitized HTML use case in real-life


10. `localStorage`

You might have used localStorage in your to-do list applications or any other projects to save the particular data in the user's computer memory. When getting and setting items, you have to use JSON parse() and stringify() methods to achieve the desired result. So, let's make it easier to work with them.

const storage = {
  get: (key, defaultValue = null) => {
    const value = localStorage.getItem(key);
    return value ? JSON.parse(value) : defaultValue;
  },
  set: (key, value) => localStorage.setItem(key, JSON.stringify(value)),
  remove: (key) => localStorage.removeItem(key),
  clear: () => localStorage.clear(),
};

storage.set("motto", "Eat, Sleep, Code, Repeat");
storage.get("motto");
Enter fullscreen mode Exit fullscreen mode

Explanation: If you aren't aware of JSON parse() and stringify() methods, check out the MDN Docs for a better explanation.

Note: It was quite tough for me to come up with a good name that would make much more sense than just storage. Because at first glance, developers might not know whether it's referring to the 'localStorage' or something else. However, you can name it whatever you want. Also, if you've found any good names, please do let me know in the comments section.


Resources

Conclusion

If you've any questions or suggestions, the comment section is all yours. We might make part 2 of this article with your suggestions.

Thanks for reading! 🙂

🔝 Back to Top

Top comments (4)

Collapse
 
tracygjg profile image
Tracy Gilmore • Edited

Hi Technophile, Nice collection. As requested, here are a couple of suggestions.

Number 4 random(): I would assume in practice this function will be called with a min parameter of zero more than any other value, so why not set it as the default? In order to do so the parameters need to be swapped so max comes first. It might also be worth considering a third parameter of precision, defaulted to zero, to provide values other than integers. The parameter can be used as a multiplier as follows 10 ** precision.

Number 10 localStorage(), could easily be extended to support sessionStorage as well, and at the same time take the key in a function.

Collapse
 
daghall profile image
Markus Daghall

Having the max parameter first is counterintuitive to me. Making the parameters dynamic is more in line with other APIs. For example:

 function random(...args) {
  if (args.length === 1) {
    args.unshift(0);
  }

  const [min, max] = args;
  return Math.floor(Math.random() * (max - min + 1)) + min;
};
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tracygjg profile image
Tracy Gilmore

Hi Markus, I can fully understand why the parameter orientation appears counterintuitive - because it is until you consider the following.

1) Out of min and max which one is most likely to change? I would say max.
2) What is likely to be the value of min in the majority of use cases? I would guess 0 and in many cases 1.
3) What is likely to be the value of max in the majority of use cases? I do not think we can guess that one.

So my rationale goes:
If the majority of calls set min to 0 we should have that as the default value. In order to set a default value, the parameter must follow all parameters without a default value. Given the range of variation in the value of max, we cannot determine a convenient default value so it will have to come before min.

Conversely, I think using the rest operator (...arg) means we do not care what order they are we can just use Math.min and Math.max to extract them, and as you have done above, set min to zero when only 1 values has been supplied. So, here is another option (no better or worse, just different.)

function random(...args) {
  const max = Math.max(...args);
  const min = (args.length === 1) ? 0 : Math.min(...args);

  return Math.floor(Math.random() * (max - min + 1)) + min;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
dostonnabotov profile image
Technophile

Thanks for the suggestions! 😃 Will definitely look into that ✔️