DEV Community

loading...
Cover image for JavaScript Functions That Will Make Your Life Much Easier [Updatable].

JavaScript Functions That Will Make Your Life Much Easier [Updatable].

youssefzidan profile image YoussefZidan Updated on ・5 min read

In this article, I will share with you some JavaScript Functions that I almost use in every single project.

Check Them in GitHub

randomNumber();

Generates a random number between min and max numbers.

/**
 * Generating random integers between min and max.
 * @param {number} min Min number
 * @param {number} max Max Number
 */
export const randomNumber = (min = 0, max = 1000) =>
  Math.ceil(min + Math.random() * (max - min));

// Example
console.log(randomNumber()); // 97
Enter fullscreen mode Exit fullscreen mode

capitalize();

Making the first letter of a string to Uppercase.

/**
 * Capitalize Strings.
 * @param {string} s String that will be Capitalized
 */
export const capitalize = (s) => {
  if (typeof s !== "string") return "";
  return s.charAt(0).toUpperCase() + s.slice(1);
};

// Example
console.log(capitalize("cat")); // Cat
Enter fullscreen mode Exit fullscreen mode

truncate();

Usually used in combination with Tooltips.

/**
 * Truncating a string...
 * @param {string} text String to be truncated
 * @param {number} num Max length of the `String` that will be truncated after
 */
export const truncate = (text, num = 10) => {
  if (text.length > num) {
    return `${text.substring(0, num - 3)}...`;
  }
  return text;
};

// Example
console.log(truncate("this is some long string to be truncated")); // this is...
Enter fullscreen mode Exit fullscreen mode

toTop();

You can remove the behavior property for instant scrolling to the top.

/**
 * Scroll to top
 */
export const toTop = () => {
  window.scroll({ top: 0, left: 0, behavior: "smooth" });
};
Enter fullscreen mode Exit fullscreen mode

softDeepClone();

Deeply clone even nested arrays or objects.

This function doesn't work with data types like new Date(), NaN, undefined, function, Number, Infinity.
If you want to deep clone the mentioned data type you can use lodash cloneDeep(); function.

/**
 * Deep cloning inputs
 * @param {any} input Input
 */
export const softDeepClone = (input) => JSON.parse(JSON.stringify(input));
Enter fullscreen mode Exit fullscreen mode

appendURLParams(); & getURLParams();

Append and get query strings, (Usually used with pagination).

/**
 * Appen query string and return the value in a query string format.
 * @param {string} key
 * @param {string} value
 */
export const appendURLParams = (paramName, value) => {
  const searchParams = new URLSearchParams(window.location.search);
  searchParams.set(paramName, value);
  return searchParams.toString();
};

// example
console.log(appendURLParams("name", "youssef")); // name=youssef

/**
 * Get param name from URL.
 * @param {string} name
 */
export const getURLParams = (name) =>
  new URLSearchParams(window.location.search).get(name);

// Example
console.log(getURLParams(id)); // 5
Enter fullscreen mode Exit fullscreen mode

getInnerHTML();

Getting inner text inside a stringed HTML.

/**
 * Getting the inner `Text` of an `HTML` string
 * @param {string} str A string of HTML
 */
export const getInnerHTML = (str) => str.replace(/(<([^>]+)>)/gi, "");
Enter fullscreen mode Exit fullscreen mode

toggleStrNum();

Usually used to deal with the server that sends and accepts string numbers.

/**
 *  returning "1" from "0" and the opposit.
 * @param {string} strNum String Number ex: "0", "1"
 */
export const toggleStrNum = (strNum) => (strNum === "0" ? "1" : "0");
Enter fullscreen mode Exit fullscreen mode

scrollToHide();

Scroll up to show the HTML element and down to hide it.

/**
 * Hide HTML element when scrolling down.
 * @param {string} id the `id` of an `HTML` element
 * @param {string} distance in px ex: "100px"
 */
export const scrollToHide = (id, distance) => {
  let prevScrollpos = window.pageYOffset;
  window.onscroll = () => {
    const currentScrollPos = window.pageYOffset;
    if (prevScrollpos > currentScrollPos) {
      document.getElementById(id).style.transform = `translateY(${distance})`;
    } else {
      document.getElementById(id).style.transform = `translateY(-${distance})`;
    }
    prevScrollpos = currentScrollPos;
  };
};
Enter fullscreen mode Exit fullscreen mode

humanFileSize ();

Converts the file size in Bytes, and Returns the result in a Human Readable formate.

/**
 * Converting Bytes to Readable Human File Sizes.
 * @param {number} bytes Bytes in Number
 */
export const humanFileSize = (bytes) => {
  let BYTES = bytes;
  const thresh = 1024;

  if (Math.abs(BYTES) < thresh) {
    return `${BYTES} B`;
  }

  const units = ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];

  let u = -1;
  const r = 10 ** 1;

  do {
    BYTES /= thresh;
    u += 1;
  } while (
    Math.round(Math.abs(BYTES) * r) / r >= thresh &&
    u < units.length - 1
  );

  return `${BYTES.toFixed(1)} ${units[u]}`;
};

// Example
console.log(humanFileSize(456465465)); // 456.5 MB
Enter fullscreen mode Exit fullscreen mode

getTimes();

Returns times of the day every n Minutes?

/**
 * Getting an Array of Times + "AM" or "PM".
 * @param {number} minutesInterval
 * @param {number} startTime
 */
export const getTimes = (minutesInterval = 15, startTime = 60) => {
  const times = []; // time array
  const x = minutesInterval; // minutes interval
  let tt = startTime; // start time
  const ap = ["AM", "PM"]; // AM-PM

  // loop to increment the time and push results in array
  for (let i = 0; tt < 24 * 60; i += 1) {
    const hh = Math.floor(tt / 60); // getting hours of day in 0-24 format
    const mm = tt % 60; // getting minutes of the hour in 0-55 format
    times[i] = `${`${hh === 12 ? 12 : hh % 12}`.slice(-2)}:${`0${mm}`.slice(
      -2
    )} ${ap[Math.floor(hh / 12)]}`; // pushing data in array in [00:00 - 12:00 AM/PM format]
    tt += x;
  }
  return times;
};

// Example
console.log(getTimes());
/* [
    "1:00 AM",
    "1:15 AM",
    "1:30 AM",
    "1:45 AM",
    "2:00 AM",
    "2:15 AM",
    "2:30 AM",
    // ....
    ]
*/
Enter fullscreen mode Exit fullscreen mode

setLocalItem(); & getLocalItem();

Caching data in LocalStorage with expiry date.

/**
 * Caching values with expiry date to the LocalHost.
 * @param {string} key Local Storage Key
 * @param {any} value Local Storage Value
 * @param {number} ttl Time to live (Expiry Date in MS)
 */
export const setLocalItem = (key, value, ttl = duration.month) => {
  const now = new Date();
  // `item` is an object which contains the original value
  // as well as the time when it's supposed to expire
  const item = {
    value,
    expiry: now.getTime() + ttl,
  };
  localStorage.setItem(key, JSON.stringify(item));
};

/**
 * Getting values with expiry date from LocalHost that stored with `setLocalItem`.
 * @param {string} key Local Storage Key
 */
export const getLocalItem = (key) => {
  const itemStr = localStorage.getItem(key);
  // if the item doesn't exist, return null
  if (!itemStr) {
    return null;
  }
  const item = JSON.parse(itemStr);
  const now = new Date();
  // compare the expiry time of the item with the current time
  if (now.getTime() > item.expiry) {
    // If the item is expired, delete the item from storage
    // and return null
    localStorage.removeItem(key);
    return null;
  }
  return item.value;
};
Enter fullscreen mode Exit fullscreen mode

logFormattedStrings();

Logs any input in a human friendly string to the console.

/**
 * Logging formatted strings
 * @param {any} input
 */
export const logFormattedStrings = (input) =>
  console.log(JSON.stringify(input, null, 4));

// Example
logFormattedStrings({ fName: "Youssef", lName: "Zidan" });
/*
 {
   "fName": "Youssef",
   "lName": "Zidan"
 } 
*/
Enter fullscreen mode Exit fullscreen mode

formatNumber();

/**
 * Format numbers with separators.
 * @param {number} num
 */
export const formatNumber = (num) => num.toLocaleString();

// Example
console.log(formatNumber(78899985)); // 78,899,985
Enter fullscreen mode Exit fullscreen mode

You can also add other options to get other number formats such as currency, distance, weights, etc...
more details HERE

And here are two examples

export const toEGPCurrency = (num) =>
  num.toLocaleString("ar-EG", { style: "currency", currency: "EGP" });

export const toUSDCurrency = (num) =>
  num.toLocaleString("en-US", { style: "currency", currency: "USD" });

console.log(toUSDCurrency(78899985)); // $78,899,985.00
console.log(toEGPCurrency(78899985)); // ٧٨٬٨٩٩٬٩٨٥٫٠٠ ج.م.
Enter fullscreen mode Exit fullscreen mode

toFormData();

/**
 * Convert Objects to Form Data Format.
 * @param {object} obj
 */
export const toFormData = (obj) => {
  const formBody = new FormData();
  Object.keys(obj).forEach((key) => {
    if (Array.isArray(obj[key])) {
      obj[key].forEach((val, i) => {
        formBody.append(`${key}[${i}]`, val);
      });
    } else formBody.append(key, obj[key]);
  });
  return formBody;
};
Enter fullscreen mode Exit fullscreen mode

getScreenWidth();

Retuns a string representing the width of the screen.

/**
 * Detect screen width and returns a string representing the width of the screen.
 */
export const getScreenWidth = () => {
  const screenWidth = window.screen.width;
  if (screenWidth <= 425) return "mobile";
  if (screenWidth <= 768) return "tablet";
  if (screenWidth <= 1024) return "laptopSm";
  if (screenWidth <= 1440) return "laptopLg";
  if (screenWidth <= 2560) return "HD";
  return screenWidth;
};
Enter fullscreen mode Exit fullscreen mode

containsAll();

Check that every element in an array exsists in the another array.

/**
 * Check that every element in an array exsists in the another array.
 * @param {array} baseArr The array to make sure it has all the values
 * @param {arr} arr The other array that will be compared with
 */
export const containsAll = (baseArr, arr) => {
  let all = false;

  for (let i = 0; i < arr.length; i += 1) {
    if (baseArr.includes(arr[i])) {
      all = true;
    } else {
      all = false;
      return all;
    }
  }

  return all;
};
Enter fullscreen mode Exit fullscreen mode

getUniqueObjs();

Returns a unique array of objects based on a key

/**
 * Returns a unique array of objects based on a key
 * @param {array} array Array of objects
 */
export const getUniqueObjs = (array, key = "id") => {
  const ids = [];
  const output = [];
  array.forEach((ele) => {
    if (!ids.includes(ele[key])) {
      ids.push(ele[key]);
      output.push(ele);
    }
  });
  return output;
};
Enter fullscreen mode Exit fullscreen mode

Do you use other useful functions? How about sharing them in the comments?

Discussion (28)

pic
Editor guide
Collapse
talorlanczyk profile image
TalOrlanczyk

for deep clone I prefer lodash because this method while it can be good in some cases it can fail.
Because it can lose data in some cases
Like Dates, functions, undefined, Infinity, RegExps, Maps, Sets, Blobs, or other complex types within your object it can be list or strigified
Its only good for object with string and numbers most of the time.
Still those are great functions that can be used in a large amount of projects

Collapse
youssefzidan profile image
YoussefZidan Author • Edited

Thanks, My friend!
I modified the article based on your feedback!

Collapse
talorlanczyk profile image
TalOrlanczyk

there is a method I use a lot when I need to submit urls

export const isUrl = (s) => {
  // eslint-disable-next-line
  var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
  return regexp.test(s);
};
Enter fullscreen mode Exit fullscreen mode
Thread Thread
youssefzidan profile image
Collapse
krimfandango profile image
Kareem Kamal • Edited

Hello, nice list!

runEvery function is broken, it runs a script every x milliseconds if hour is after the given hour and minute is after the given minute, so given this input:

runEvery(() => console.log('ran'), 12, 30, 300000)
Enter fullscreen mode Exit fullscreen mode

and the time now is 3:17 PM it will try running at 8:17 PM but now.getMinutes() >= mins will return false and the function will not execute, and every 5 hours it will always return false
But if you set minutes to 0 or someone starts the application after the provided minute it will execute every interval after the given time.

If the goal is to make a function that runs every day at a certain time, you need to get the time to the next occurrence and start the interval then, something like this:

function runEverydayAt(callback, hour, minute) {
  // first we need to get the time until the next hour:minute
  const now = new Date()
  // to check if the next time happens today check how many minutes
  // passed in the day and compare them with the input
  const nowInMinutes = (now.getHours() * 60) + now.getMinutes()
  const inputTimeInMinutes = (hour * 60) + minute
  const isNextTimeToday = nowInMinutes < inputTimeInMinutes

  // create a new date for the comparison
  const firstTime = new Date()
  // and set its time to the input's time
  firstTime.setHours(hour, minute, 0)

  if (!isNextTimeToday) {
    // if next time is today then add a day
    firstTime.setDate(now.getDate() + 1)
  }

  const timeUntilNextOccurrence = firstTime.getTime() - now.getTime()

  // finally set a timeout to start the first call
  // on time then every other call every 24 hours
  setTimeout(() => {
    // setInterval will start kicking in after 24 hours
    // therefore we need to invoke the first callback here
    callback()
    setInterval(callback, 1000 * 60 * 60 * 24)
  }, timeUntilNextOccurrence)
}

// to check you can try invoking it with a time that's coming soon
runEverydayAt(() => console.log('I ran!'), 10, 43)
Enter fullscreen mode Exit fullscreen mode
Collapse
youssefzidan profile image
YoussefZidan Author

Great!
Thanks for your feedback!
I'll check my code again and get back to you.

Collapse
youssefzidan profile image
YoussefZidan Author • Edited

Hello!
I tried to run your function but it doesn't seem to be working.

Thread Thread
krimfandango profile image
Kareem Kamal

Hey Youssif, I've just tried running the code in the console and it seems to be working.
You just need to set the time to be coming up in a minute or two so that you wouldn't wait for long for the next occurrence

Image

Collapse
mma1979 profile image
Mohammed Abdelhay

and this one I am using regularly

// serialize javascript object into url query string
        Serialize = function (obj) {
            var str = [];
            for (var p in obj)
                if (obj.hasOwnProperty(p) && obj[p] != null && obj[p].toString() != '') {
                    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                }
            return str.join("&");
        }

Enter fullscreen mode Exit fullscreen mode
Collapse
youssefzidan profile image
YoussefZidan Author

Nice!
I like it!

Collapse
endrureza profile image
Endru Reza

i think it would be good for you to create this into an npm package.

Collapse
youssefzidan profile image
YoussefZidan Author

It's on my plan but i need to increase the number of functions.

Collapse
talorlanczyk profile image
TalOrlanczyk

I would like to help with the npm

Thread Thread
halbano profile image
halbano • Edited

I would like to help too. Maybe we can build something bigger between us!
I have a bunch of react-native utils that may be interesting.

Thread Thread
youssefzidan profile image
YoussefZidan Author

That's great!
Maybe we can do something together.

Collapse
metruzanca profile image
Samuele Zanca

The way you're deep cloning is bad practice. If you're gonna copy and paste helpers might as ok copy and paste lodash's implementation.

Collapse
youssefzidan profile image
YoussefZidan Author

Thanks, My friend!
I modified the article based on your feedback!

Collapse
hellonearthis profile image
Brett Cooper

1024 = 1k bytes

Collapse
youssefzidan profile image
YoussefZidan Author

Thanks, My friend!
I modified the article based on your feedback!

Collapse
pavlosisaris profile image
Paul Isaris

Nice collection, thanks!

Collapse
qq449245884 profile image
qq449245884

Dear YoussefZidan,may I translate your article into Chinese?I would like to share it with more developers in China. I will give the original author and original source.

Collapse
youssefzidan profile image
Collapse
lovesponge profile image
Guy

Great Post!
I use Number.prototype.toLocaleString() to get formatted numbers 😁

Collapse
youssefzidan profile image
YoussefZidan Author

This is amazing!
Thanks for sharing!

Collapse
youssefzidan profile image
YoussefZidan Author

I Modified the article based on your feedback!
Thanks, my friend!

Collapse
nilsandrey profile image
Nils Andrey

Thanks for sharing. I recommend you to create a Github gist for most of it and share the links here.

Collapse
youssefzidan profile image
YoussefZidan Author

Thanks, Sure I'll do so.

Collapse
matthijsewoud profile image
⚡️

That function where you try to parse HTML with regex doesn’t feel safe. You can't parse [X]HTML with regex. Because HTML can't be parsed by regex. Regex is not a tool that can be used to correctly parse HTML. As I have answered in HTML-and-regex questions here so many times before, the use of regex will not allow you to consume HTML. Regular expressions are a tool that is insufficiently sophisticated to understand the constructs employed by HTML. HTML is not a regular language and hence cannot be parsed by regular expressions. Regex queries are not equipped to break down HTML into its meaningful parts. so many times but it is not getting to me. Even enhanced irregular regular expressions as used by Perl are not up to the task of parsing HTML. You will never make me crack. HTML is a language of sufficient complexity that it cannot be parsed by regular expressions. Even Jon Skeet cannot parse HTML using regular expressions. Every time you attempt to parse HTML with regular expressions, the unholy child weeps the blood of virgins, and Russian hackers pwn your webapp. Parsing HTML with regex summons tainted souls into the realm of the living. HTML and regex go together like love, marriage, and ritual infanticide. The

cannot hold it is too late. The force of regex and HTML together in the same conceptual space will destroy your mind like so much watery putty. If you parse HTML with regex you are giving in to Them and their blasphemous ways which doom us all to inhuman toil for the One whose Name cannot be expressed in the Basic Multilingual Plane, he comes. HTML-plus-regexp will liquify the n​erves of the sentient whilst you observe, your psyche withering in the onslaught of horror. Rege̿̔̉x-based HTML parsers are the cancer that is killing StackOverflow it is too late it is too late we cannot be saved the transgression of a chi͡ld ensures regex will consume all living tissue (except for HTML which it cannot, as previously prophesied) dear lord help us how can anyone survive this scourge using regex to parse HTML has doomed humanity to an eternity of dread torture and security holes using regex as a tool to process HTML establishes a breach between this world and the dread realm of c͒ͪo͛ͫrrupt entities (like SGML entities, but more corrupt) a mere glimpse of the world of reg​ex parsers for HTML will ins​tantly transport a programmer's consciousness into a world of ceaseless screaming, he comes, the pestilent slithy regex-infection wil​l devour your HT​ML parser, application and existence for all time like Visual Basic only worse he comes he comes do not fi​ght he com̡e̶s, ̕h̵i​s un̨ho͞ly radiańcé destro҉ying all enli̍̈́̂̈́ghtenment, HTML tags lea͠ki̧n͘g fr̶ǫm ̡yo​͟ur eye͢s̸ ̛l̕ik͏e liq​uid pain, the song of re̸gular exp​ression parsing will exti​nguish the voices of mor​tal man from the sp​here I can see it can you see ̲͚̖͔̙î̩́t̲͎̩̱͔́̋̀ it is beautiful t​he final snuffing of the lie​s of Man ALL IS LOŚ͖̩͇̗̪̏̈́T ALL I​S LOST the pon̷y he comes he c̶̮omes he comes the ich​or permeates all MY FACE MY FACE ᵒh god no NO NOO̼O​O NΘ stop the an​*̶͑̾̾​̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨe̠̅s ͎a̧͈͖r̽̾̈́͒͑e n​ot rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚​N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ