Utility
castArray
Casts the provided value as an array if it's not one.
Use Array.prototype.isArray()
to determine if val
is an array and return it as-is or encapsulated in an array accordingly.
如果提供的值不是数组,则将其转换为数组。
使用 array.prototype.isarray()
来确定 val
是否是一个数组,如果是数组,按原样返回;如果不是数组,将值封装在数组中返回。
const castArray = val => (Array.isArray(val) ? val : [val]);
castArray('foo'); // ['foo'] castArray([1]); // [1]
cloneRegExp
Clones a regular expression.
Use new RegExp()
, RegExp.source
and RegExp.flags
to clone the given regular expression.
克隆一个正则表达式。
使用 new RegExp()
, RegExp.source
和 RegExp.flags
来克隆给定的正则表达式。
const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
const regExp = /lorem ipsum/gi; const regExp2 = cloneRegExp(regExp); // /lorem ipsum/gi
coalesce
Returns the first non-null/undefined argument.
Use Array.prototype.find()
to return the first non null
/undefined
argument.
返回第一个不是 null
或 undefined
的参数。
使用 Array.prototype.find()
返回第一个不是 null
或 undefined
的参数。
const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
coalesce(null, undefined, '', NaN, 'Waldo'); // ""
coalesceFactory
Returns a customized coalesce function that returns the first argument that returns true
from the provided argument validation function.
Use Array.prototype.find()
to return the first argument that returns true
from the provided argument validation function.
返回一个自定义的 coalesce
函数,该函数返回从提供的参数验证函数返回为 true
的第一个参数。
使用 Array.prototype.find()
返回从提供的参数验证函数返回 true
的第一个参数。
const coalesceFactory = valid => (...args) => args.find(valid);
const customCoalesce = coalesceFactory(_ => ![null, undefined, '', NaN].includes(_)); customCoalesce(undefined, null, NaN, '', 'Waldo'); // "Waldo"
extendHex
Extends a 3-digit color code to a 6-digit color code.
Use Array.prototype.map()
, String.prototype.split()
and Array.prototype.join()
to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. Array.prototype.slice()
is used to remove #
from string start since it's added once.
const extendHex = shortHex => '#' + shortHex .slice(shortHex.startsWith('#') ? 1 : 0) .split('') .map(x => x + x) .join('');
extendHex('#03f'); // '#0033ff' extendHex('05a'); // '#0055aa'
getURLParameters
Returns an object containing the parameters of the current URL.
Use String.match()
with an appropriate regular expression to get all key-value pairs, Array.prototype.reduce()
to map and combine them into a single object. Pass location.search
as the argument to apply to the current url
.
const getURLParameters = url => (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), {} );
getURLParameters('http://url.com/page?name=Adam&surname=Smith'); // {name: 'Adam', surname: 'Smith'} getURLParameters('google.com'); // {}
hexToRGB
Converts a color code to a rgb()
or rgba()
string if alpha value is provided.
Use bitwise right-shift operator and mask bits with &
(and) operator to convert a hexadecimal color code (with or without prefixed with #
) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If an alpha value is provided alongside 6-digit hex, give rgba()
string in return.
const hexToRGB = hex => { let alpha = false, h = hex.slice(hex.startsWith('#') ? 1 : 0); if (h.length === 3) h = [...h].map(x => x + x).join(''); else if (h.length === 8) alpha = true; h = parseInt(h, 16); return ( 'rgb' + (alpha ? 'a' : '') + '(' + (h >>> (alpha ? 24 : 16)) + ', ' + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + ', ' + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + (alpha ? `, ${h & 0x000000ff}` : '') + ')' ); };
hexToRGB('#27ae60ff'); // 'rgba(39, 174, 96, 255)' hexToRGB('27ae60'); // 'rgb(39, 174, 96)' hexToRGB('#fff'); // 'rgb(255, 255, 255)'
httpGet
Makes a GET
request to the passed URL.
Use XMLHttpRequest
web api to make a get
request to the given url
. Handle the onload
event, by calling the given callback
the responseText
. Handle the onerror
event, by running the provided err
function. Omit the third argument, err
, to log errors to the console's error
stream by default.
const httpGet = (url, callback, err = console.error) => { const request = new XMLHttpRequest(); request.open('GET', url, true); request.onload = () => callback(request.responseText); request.onerror = () => err(request); request.send(); };
httpGet( 'https://jsonplaceholder.typicode.com/posts/1', console.log ); /* Logs: { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" } */
httpPost
Makes a POST
request to the passed URL.
Use XMLHttpRequest
web api to make a post
request to the given url
. Set the value of an HTTP
request header with setRequestHeader
method. Handle the onload
event, by calling the given callback
the responseText
. Handle the onerror
event, by running the provided err
function. Omit the third argument, data
, to send no data to the provided url
. Omit the fourth argument, err
, to log errors to the console's error
stream by default.
const httpPost = (url, data, callback, err = console.error) => { const request = new XMLHttpRequest(); request.open('POST', url, true); request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); request.onload = () => callback(request.responseText); request.onerror = () => err(request); request.send(data); };
const newPost = { userId: 1, id: 1337, title: 'Foo', body: 'bar bar bar' }; const data = JSON.stringify(newPost); httpPost( 'https://jsonplaceholder.typicode.com/posts', data, console.log ); /* Logs: { "userId": 1, "id": 1337, "title": "Foo", "body": "bar bar bar" } */ httpPost( 'https://jsonplaceholder.typicode.com/posts', null, // does not send a body console.log ); /* Logs: { "id": 101 } */
isBrowser
Determines if the current runtime environment is a browser so that front-end modules can run on the server (Node) without throwing errors.
Use Array.prototype.includes()
on the typeof
values of both window
and document
(globals usually only available in a browser environment unless they were explicitly defined), which will return true
if one of them is undefined
. typeof
allows globals to be checked for existence without throwing a ReferenceError
. If both of them are not undefined
, then the current environment is assumed to be a browser.
const isBrowser = () => ![typeof window, typeof document].includes('undefined');
isBrowser(); // true (browser) isBrowser(); // false (Node)
mostPerformant
Returns the index of the function in an array of functions which executed the fastest.
Use Array.prototype.map()
to generate an array where each value is the total time taken to execute the function after iterations
times. Use the difference in performance.now()
values before and after to get the total time in milliseconds to a high degree of accuracy. Use Math.min()
to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function. Omit the second argument, iterations
, to use a default of 10,000 iterations. The more iterations, the more reliable the result but the longer it will take.
const mostPerformant = (fns, iterations = 10000) => { const times = fns.map(fn => { const before = performance.now(); for (let i = 0; i < iterations; i++) fn(); return performance.now() - before; }); return times.indexOf(Math.min(...times)); };
mostPerformant([ () => { // Loops through the entire array before returning `false` [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number'); }, () => { // Only needs to reach index `1` before returning false [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number'); } ]); // 1
nthArg
Creates a function that gets the argument at index n
. If n
is negative, the nth argument from the end is returned.
Use Array.prototype.slice()
to get the desired argument at index n
.
const nthArg = n => (...args) => args.slice(n)[0];
const third = nthArg(2); third(1, 2, 3); // 3 third(1, 2); // undefined const last = nthArg(-1); last(1, 2, 3, 4, 5); // 5
parseCookie
Parse an HTTP Cookie header string and return an object of all cookie name-value pairs.
Use String.prototype.split(';')
to separate key-value pairs from each other. Use Array.prototype.map()
and String.prototype.split('=')
to separate keys from values in each pair. Use Array.prototype.reduce()
and decodeURIComponent()
to create an object with all key-value pairs.
const parseCookie = str => str .split(';') .map(v => v.split('=')) .reduce((acc, v) => { acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); return acc; }, {});
parseCookie('foo=bar; equation=E%3Dmc%5E2'); // { foo: 'bar', equation: 'E=mc^2' }
Recommended Resource - JavaScript: From Fundamentals to Functional JS
Learn higher-order functions, closures, scope, master key functional methods like map, reduce and filter and promises and ES6+ asynchronous JavaScript.
prettyBytes
Converts a number in bytes to a human-readable string.
Use an array dictionary of units to be accessed based on the exponent. Use Number.toPrecision()
to truncate the number to a certain number of digits. Return the prettified string by building it up, taking into account the supplied options and whether it is negative or not. Omit the second argument, precision
, to use a default precision of 3
digits. Omit the third argument, addSpace
, to add space between the number and unit by default.
const prettyBytes = (num, precision = 3, addSpace = true) => { const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; };
prettyBytes(1000); // "1 KB" prettyBytes(-27145424323.5821, 5); // "-27.145 GB" prettyBytes(123456789, 3, false); // "123MB"
randomHexColorCode
Generates a random hexadecimal color code.
Use Math.random
to generate a random 24-bit(6x4bits) hexadecimal number. Use bit shifting and then convert it to an hexadecimal String using toString(16)
.
const randomHexColorCode = () => { let n = (Math.random() * 0xfffff * 1000000).toString(16); return '#' + n.slice(0, 6); };
randomHexColorCode(); // "#e34155"
RGBToHex
Converts the values of RGB components to a color code.
Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (<<
) and toString(16)
, then String.padStart(6,'0')
to get a 6-digit hexadecimal value.
const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
RGBToHex(255, 165, 1); // 'ffa501'
serializeCookie
Serialize a cookie name-value pair into a Set-Cookie header string.
Use template literals and encodeURIComponent()
to create the appropriate string.
const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;
serializeCookie('foo', 'bar'); // 'foo=bar'
timeTaken
Measures the time taken by a function to execute.
Use console.time()
and console.timeEnd()
to measure the difference between the start and end times to determine how long the callback took to execute.
const timeTaken = callback => { console.time('timeTaken'); const r = callback(); console.timeEnd('timeTaken'); return r; };
timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms
toCurrency
Take a number and return specified currency formatting.
Use Intl.NumberFormat
to enable country / currency sensitive formatting.
const toCurrency = (n, curr, LanguageFormat = undefined) => Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
toCurrency(123456.789, 'EUR'); // €123,456.79 | currency: Euro | currencyLangFormat: Local toCurrency(123456.789, 'USD', 'en-us'); // $123,456.79 | currency: US Dollar | currencyLangFormat: English (United States) toCurrency(123456.789, 'USD', 'fa'); // ۱۲۳٬۴۵۶٫۷۹ $ | currency: US Dollar | currencyLangFormat: Farsi toCurrency(322342436423.2435, 'JPY'); // ¥322,342,436,423 | currency: Japanese Yen | currencyLangFormat: Local toCurrency(322342436423.2435, 'JPY', 'fi'); // 322 342 436 423 ¥ | currency: Japanese Yen | currencyLangFormat: Finnish
toDecimalMark
Use toLocaleString()
to convert a float-point arithmetic to the Decimal mark form. It makes a comma separated string from a number.
const toDecimalMark = num => num.toLocaleString('en-US');
toDecimalMark(12305030388.9087); // "12,305,030,388.909"
toOrdinalSuffix
Adds an ordinal suffix to a number.
Use the modulo operator (%
) to find values of single and tens digits. Find which ordinal pattern digits match. If digit is found in teens pattern, use teens ordinal.
const toOrdinalSuffix = num => { const int = parseInt(num), digits = [int % 10, int % 100], ordinals = ['st', 'nd', 'rd', 'th'], oPattern = [1, 2, 3, 4], tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) ? int + ordinals[digits[0] - 1] : int + ordinals[3]; };
toOrdinalSuffix('123'); // "123rd"
validateNumber
Returns true
if the given value is a number, false
otherwise.
Use !isNaN()
in combination with parseFloat()
to check if the argument is a number. Use isFinite()
to check if the number is finite. Use Number()
to check if the coercion holds.
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
validateNumber('10'); // true
yesNo
Returns true
if the string is y
/yes
or false
if the string is n
/no
.
Use RegExp.test()
to check if the string evaluates to y/yes
or n/no
. Omit the second argument, def
to set the default answer as no
.
const yesNo = (val, def = false) => /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;
yesNo('Y'); // true yesNo('yes'); // true yesNo('No'); // false yesNo('Foo', true); // true