Array
将值转换为数组#
const castArray = (value) => (Array.isArray(value) ? value : [value]);
// Examples
castArray(1); // [1]
castArray([1, 2, 3]); // [1, 2, 3]
检查数组是否为空#
// `arr` is an array
const isEmpty = (arr) => !Array.isArray(arr) || arr.length === 0;
// Examples
isEmpty([]); // true
isEmpty([1, 2, 3]); // false
克隆数组#
// `arr` is an array
const clone = (arr) => arr.slice(0);
// Or
const clone = (arr) => [...arr];
// Or
const clone = (arr) => Array.from(arr);
// Or
const clone = (arr) => arr.map((x) => x);
// Or
const clone = (arr) => JSON.parse(JSON.stringify(arr));
// Or
const clone = (arr) => arr.concat([]);
比较两个数组,而不考虑顺序#
// `a` and `b` are arrays
const isEqual = (a, b) => JSON.stringify(a.sort()) === JSON.stringify(b.sort());
// Examples
isEqual([1, 2, 3], [1, 2, 3]); // true
isEqual([1, 2, 3], [1, 3, 2]); // true
isEqual([1, 2, 3], [1, "2", 3]); // false
比较两个数组#
// `a` and `b` are arrays
const isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
// Or
const isEqual = (a, b) =>
a.length === b.length && a.every((v, i) => v === b[i]);
// Examples
isEqual([1, 2, 3], [1, 2, 3]); // true
isEqual([1, 2, 3], [1, "2", 3]); // false
将对象数组转换为单个对象#
const toObject = (arr, key) =>
arr.reduce((a, b) => ({ ...a, [b[key]]: b }), {});
// Example
toObject(
[
{ id: "1", name: "Alpha", gender: "Male" },
{ id: "2", name: "Bravo", gender: "Male" },
{ id: "3", name: "Charlie", gender: "Female" },
],
"id"
);
/*
{
'1': { id: '1', name: 'Alpha', gender: 'Male' },
'2': { id: '2', name: 'Bravo', gender: 'Male' },
'3': { id: '3', name: 'Charlie', gender: 'Female' },
}
*/
将字符串数组转换为数字#
const toNumbers = (arr) => arr.map(Number);
// Or
const toNumbers = (arr) => arr.map((x) => +x);
// Example
toNumbers(["2", "3", "4"]); // [2, 3, 4]
通过对象数组的属性进行计数#
const countBy = (arr, prop) =>
arr.reduce(
(prev, curr) => ((prev[curr[prop]] = ++prev[curr[prop]] || 1), prev),
{}
);
// Example
countBy(
[
{ branch: "audi", model: "q8", year: "2019" },
{ branch: "audi", model: "rs7", year: "2020" },
{ branch: "ford", model: "mustang", year: "2019" },
{ branch: "ford", model: "explorer", year: "2020" },
{ branch: "bmw", model: "x7", year: "2020" },
],
"branch"
);
// { 'audi': 2, 'ford': 2, 'bmw': 1 }
计算数组中某个值的出现#
const countOccurrences = (arr, val) =>
arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
// Or
const countOccurrences = (arr, val) =>
arr.filter((item) => item === val).length;
// Examples
countOccurrences([2, 1, 3, 3, 2, 3], 2); // 2
countOccurrences(["a", "b", "a", "c", "a", "b"], "a"); // 3
计算数组元素的出现#
const countOccurrences = (arr) =>
arr.reduce((prev, curr) => ((prev[curr] = ++prev[curr] || 1), prev), {});
// Examples
countOccurrences([2, 1, 3, 3, 2, 3]); // { '1': 1, '2': 2, '3': 3 }
countOccurrences(["a", "b", "a", "c", "a", "b"]); // { 'a': 3, 'b': 2, 'c': 1 }
创建一个累加和数组#
const accumulate = (arr) =>
arr.map(
(
(sum) => (value) =>
(sum += value)
)(0)
);
// Or
const accumulate = (arr) =>
arr.reduce((a, b, i) => (i === 0 ? [b] : [...a, b + a[i - 1]]), []);
// Or
const accumulate = (arr) =>
arr.reduce((a, b, i) => (i === 0 ? [b] : [...a, b + a[i - 1]]), 0);
// Example
accumulate([1, 2, 3, 4]); // [1, 3, 6, 10]
// 1 = 1
// 1 + 2 = 3
// 1 + 2 + 3 = 6
// 1 + 2 + 3 + 4 = 10
在给定范围内创建一个数字数组#
const range = (min, max) =>
[...Array(max - min + 1).keys()].map((i) => i + min);
// Or
const range = (min, max) =>
Array(max - min + 1)
.fill(0)
.map((_, i) => min + i);
// Or
const range = (min, max) =>
Array.from({ length: max - min + 1 }, (_, i) => min + i);
// Example
range(5, 10); // [5, 6, 7, 8, 9, 10]
创建笛卡尔积#
const cartesian = (...sets) =>
sets.reduce(
(acc, set) => acc.flatMap((x) => set.map((y) => [...x, y])),
[[]]
);
// Example
cartesian([1, 2], [3, 4]); // [ [1, 3], [1, 4], [2, 3], [2, 4] ]
/*
3 4
---------------
1 | [1, 3] [1, 4]
|
2 | [2, 3] [2, 4]
*/
清空数组#
const empty = (arr) => (arr.length = 0);
// Or
arr = [];
从数组中找到最接近的数字#
// Find the number from `arr` which is closest to `n`
const closest = (arr, n) =>
arr.reduce((prev, curr) =>
Math.abs(curr - n) < Math.abs(prev - n) ? curr : prev
);
// Or
const closest = (arr, n) =>
arr.sort((a, b) => Math.abs(a - n) - Math.abs(b - n))[0];
// Example
closest([29, 87, 8, 78, 97, 20, 75, 33, 24, 17], 50); // 33
查找数组中最后一个匹配项的索引#
const lastIndex = (arr, predicate) =>
arr.reduce((prev, curr, index) => (predicate(curr) ? index : prev), -1);
// Or
const lastIndex = (arr, predicate) =>
arr.map((item) => predicate(item)).lastIndexOf(true);
// Example
lastIndex([1, 3, 5, 7, 9, 2, 4, 6, 8], (i) => i % 2 === 1); // 4
lastIndex([1, 3, 5, 7, 9, 8, 6, 4, 2], (i) => i > 6); // 5
查找数组中最大项的索引#
const indexOfMax = (arr) =>
arr.reduce((prev, curr, i, a) => (curr > a[prev] ? i : prev), 0);
// Examples
indexOfMax([1, 3, 9, 7, 5]); // 2
indexOfMax([1, 3, 7, 7, 5]); // 2
查找数组最小项的索引#
const indexOfMin = (arr) =>
arr.reduce((prev, curr, i, a) => (curr < a[prev] ? i : prev), 0);
// Examples
indexOfMin([6, 4, 8, 2, 10]); // 3
indexOfMin([6, 4, 2, 2, 10]); // 2
查找数组中最长字符串的长度#
const findLongest = (words) => Math.max(...words.map((el) => el.length));
// Example
findLongest(["always", "look", "on", "the", "bright", "side", "of", "life"]); // 6
通过给定键找到数组的最大项#
const maxBy = (arr, key) =>
arr.reduce((a, b) => (a[key] >= b[key] ? a : b), {});
// Example
const people = [
{ name: "Bar", age: 24 },
{ name: "Baz", age: 32 },
{ name: "Foo", age: 42 },
{ name: "Fuzz", age: 36 },
];
maxBy(people, "age"); // { name: 'Foo', age: 42 }
查找数组的最大项#
const max = (arr) => Math.max(...arr);
通过给定键找到数组的最小项#
const minBy = (arr, key) => arr.reduce((a, b) => (a[key] < b[key] ? a : b), {});
// Example
const people = [
{ name: "Bar", age: 24 },
{ name: "Baz", age: 32 },
{ name: "Foo", age: 42 },
{ name: "Fuzz", age: 36 },
];
minBy(people, "age"); // { name: 'Bar', age: 24 }
查找数组的最小项#
const min = (arr) => Math.min(...arr);
展平数组#
const flat = (arr) =>
[].concat.apply(
[],
arr.map((a) => (Array.isArray(a) ? flat(a) : a))
);
// Or
const flat = (arr) =>
arr.reduce((a, b) => (Array.isArray(b) ? [...a, ...flat(b)] : [...a, b]), []);
// Or
// See the browser compatibility at https://caniuse.com/#feat=array-flat
const flat = (arr) => arr.flat();
// Example
flat(["cat", ["lion", "tiger"]]); // ['cat', 'lion', 'tiger']
获取所有连续元素的数组#
const getConsecutiveArrays = (arr, size) =>
size > arr.length
? []
: arr.slice(size - 1).map((_, i) => arr.slice(i, size + i));
// Examples
getConsecutiveArrays([1, 2, 3, 4, 5], 2); // [[1, 2], [2, 3], [3, 4], [4, 5]]
getConsecutiveArrays([1, 2, 3, 4, 5], 3); // [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
getConsecutiveArrays([1, 2, 3, 4, 5], 6); // []
获取数组的所有n项#
const getNthItems = (arr, nth) => arr.filter((_, i) => i % nth === nth - 1);
// Examples
getNthItems([1, 2, 3, 4, 5, 6, 7, 8, 9], 2); // [2, 4, 6, 8]
getNthItems([1, 2, 3, 4, 5, 6, 7, 8, 9], 3); // [3, 6, 9]
获取数组的所有子集#
const getSubsets = (arr) =>
arr.reduce(
(prev, curr) => prev.concat(prev.map((k) => k.concat(curr))),
[[]]
);
// Examples
getSubsets([1, 2]); // [[], [1], [2], [1, 2]]
getSubsets([1, 2, 3]); // [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
获取数组中值的索引#
const indices = (arr, value) =>
arr.reduce((acc, v, i) => (v === value ? [...acc, i] : acc), []);
// Or
const indices = (arr, value) =>
arr.map((v, i) => (v === value ? i : false)).filter(Boolean);
// Examples
indices(["h", "e", "l", "l", "o"], "l"); // [2, 3]
indices(["h", "e", "l", "l", "o"], "w"); // []
获取数组的平均值#
const average = (arr) => arr.reduce((a, b) => a + b, 0) / arr.length;
获取数组的交集#
const getIntersection = (a, ...arr) =>
[...new Set(a)].filter((v) => arr.every((b) => b.includes(v)));
// Examples
getIntersection([1, 2, 3], [2, 3, 4, 5]); // [2, 3]
getIntersection([1, 2, 3], [2, 3, 4, 5], [1, 3, 5]); // [3]
获取一个数字数组的等级#
const ranking = (arr) =>
arr.map((x, y, z) => z.filter((w) => w > x).length + 1);
// Examples
ranking([80, 65, 90, 50]); // [2, 3, 1, 4]
ranking([80, 80, 70, 50]); // [1, 1, 3, 4]
ranking([80, 80, 80, 50]); // [1, 1, 1, 4]
获得一个数字数组的和#
const sum = (arr) => arr.reduce((a, b) => a + b, 0);
获取数组的唯一值#
const unique = (arr) => [...new Set(arr)];
// Or
const unique = (arr) => arr.filter((el, i, array) => array.indexOf(el) === i);
// Or
const unique = (arr) =>
arr.reduce((acc, el) => (acc.includes(el) ? acc : [...acc, el]), []);
获得数组的并集#
const union = (...arr) => [...new Set(arr.flat())];
// Example
union([1, 2], [2, 3], [3]); // [1, 2, 3]
通过键将对象数组进行分组#
const groupBy = (arr, key) =>
arr.reduce(
(acc, item) => ((acc[item[key]] = [...(acc[item[key]] || []), item]), acc),
{}
);
// Example
groupBy(
[
{ branch: "audi", model: "q8", year: "2019" },
{ branch: "audi", model: "rs7", year: "2020" },
{ branch: "ford", model: "mustang", year: "2019" },
{ branch: "ford", model: "explorer", year: "2020" },
{ branch: "bmw", model: "x7", year: "2020" },
],
"branch"
);
/*
{
audi: [
{ branch: 'audi', model: 'q8', year: '2019' },
{ branch: 'audi', model: 'rs7', year: '2020' }
],
bmw: [
{ branch: 'bmw', model: 'x7', year: '2020' }
],
ford: [
{ branch: 'ford', model: 'mustang', year: '2019' },
{ branch: 'ford', model: 'explorer', year: '2020' }
],
}
*/
合并两个数组#
// Merge but don't remove the duplications
const merge = (a, b) => a.concat(b);
// Or
const merge = (a, b) => [...a, ...b];
// Merge and remove the duplications
const merge = [...new Set(a.concat(b))];
// Or
const merge = [...new Set([...a, ...b])];
根据条件对数组进行分区#
const partition = (arr, criteria) =>
arr.reduce((acc, i) => (acc[criteria(i) ? 0 : 1].push(i), acc), [[], []]);
// Example
partition([1, 2, 3, 4, 5], (n) => n % 2); // [[2, 4], [1, 3, 5]]
删除数组中的重复值#
const removeDuplicate = (arr) =>
arr.filter((i) => arr.indexOf(i) === arr.lastIndexOf(i));
// Example
removeDuplicate(["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]); // ['h', 'e', 'w', 'r', 'd']
从数组中删除虚假值#
const removeFalsy = (arr) => arr.filter(Boolean);
// Example
removeFalsy([
0,
"a string",
"",
NaN,
true,
5,
undefined,
"another string",
false,
]); // ['a string', true, 5, 'another string']
随机排列数组#
const shuffle = (arr) =>
arr
.map((a) => ({ sort: Math.random(), value: a }))
.sort((a, b) => a.sort - b.sort)
.map((a) => a.value);
// Or
const shuffle = (arr) => arr.sort(() => 0.5 - Math.random());
// Example
shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); // [9, 1, 10, 6, 8, 5, 2, 3, 7, 4]
按给定键对项目数组进行排序#
const sortBy = (arr, k) =>
arr.concat().sort((a, b) => (a[k] > b[k] ? 1 : a[k] < b[k] ? -1 : 0));
// Example
const people = [
{ name: "Foo", age: 42 },
{ name: "Bar", age: 24 },
{ name: "Fuzz", age: 36 },
{ name: "Baz", age: 32 },
];
sortBy(people, "age");
// returns
// [
// { name: 'Bar', age: 24 },
// { name: 'Baz', age: 32 },
// { name: 'Fuzz', age: 36 },
// { name: 'Foo', age: 42 },
// ]
对数字数组进行排序#
const sort = (arr) => arr.sort((a, b) => a - b);
// Example
sort([1, 5, 2, 4, 3]); // [1, 2, 3, 4, 5]
将数组拆分为块#
const chunk = (arr, size) =>
arr.reduce(
(acc, e, i) => (
i % size ? acc[acc.length - 1].push(e) : acc.push([e]), acc
),
[]
);
// Examples
chunk([1, 2, 3, 4, 5, 6, 7, 8], 3); // [[1, 2, 3], [4, 5, 6], [7, 8]]
chunk([1, 2, 3, 4, 5, 6, 7, 8], 4); // [[1, 2, 3, 4], [5, 6, 7, 8]]
交换矩阵的行和列#
const transpose = (matrix) =>
matrix[0].map((col, i) => matrix.map((row) => row[i]));
// Or
const transpose = (matrix) =>
matrix[0].map((col, c) => matrix.map((row, r) => matrix[r][c]));
// Or
const transpose = (matrix) =>
matrix.reduce(
(prev, next) => next.map((item, i) => (prev[i] || []).concat(next[i])),
[]
);
// Example
transpose([
// [
[1, 2, 3], // [1, 4, 7],
[4, 5, 6], // [2, 5, 8],
[7, 8, 9], // [3, 6, 9],
]); // ]
交换两个数组项#
// `i` must be less than `j`
const swapItems = (a, i, j) =>
(a[i] &&
a[j] && [
...a.slice(0, i),
a[j],
...a.slice(i + 1, j),
a[i],
...a.slice(j + 1),
]) ||
a;
// Example
swapItems([1, 2, 3, 4, 5], 1, 4); // [1, 5, 3, 4, 2]
解压缩数组的数组#
const unzip = (arr) =>
arr.reduce(
(acc, c) => (c.forEach((v, i) => acc[i].push(v)), acc),
Array.from({ length: Math.max(...arr.map((a) => a.length)) }, (_) => [])
);
// Example
unzip([
["a", 1],
["b", 2],
["c", 3],
["d", 4],
["e", 5],
]); // [['a', 'b', 'c', 'd', 'e'], [1, 2, 3, 4, 5]]
/*
a 1
b 2
c 3
d 4
e 5
*/
压缩多个数组#
const zip = (...arr) =>
Array.from({ length: Math.max(...arr.map((a) => a.length)) }, (_, i) =>
arr.map((a) => a[i])
);
// Example
zip(["a", "b", "c", "d", "e"], [1, 2, 3, 4, 5]); // [['a', 1], ['b', 2], ['c', 3], ['d', 4], ['e', 5]]
/*
Does it look like a zipper?
a 1
b 2
c 3
d 4
e 5
*/
DOM
检查一个元素是否是另一个元素的后代#
const isDescendant = (child, parent) => parent.contains(child);
检查一个元素是否聚焦#
const hasFocus = (ele) => ele === document.activeElement;
检查是否支持触摸事件#
const touchSupported = () =>
"ontouchstart" in window ||
(window.DocumentTouch && document instanceof window.DocumentTouch);
检查用户是否滚动到页面底部#
const isAtBottom = () =>
document.documentElement.clientHeight + window.scrollY >=
document.documentElement.scrollHeight;
检测Internet Explorer浏览器#
const isIE = !!document.documentMode;
检测macOS浏览器#
const isMacBrowser = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
获取元素的所有同级#
const siblings = (ele) =>
[].slice.call(ele.parentNode.children).filter((child) => child !== ele);
获取元素相对于文档的位置#
const getPosition = (ele) => (
(r = ele.getBoundingClientRect()),
{ left: r.left + window.scrollX, top: r.top + window.scrollY }
);
// Example
getPosition(document.body); // { left: 0, top: 0 }
获取选定的文本#
const getSelectedText = () => window.getSelection().toString();
返回上一个页面#
history.back();
// Or
history.go(-1);
隐藏元素#
// Pick the method that is suitable for your use case
const hide = (ele) => (ele.style.display = "none");
// Or
const hide = (ele) => (ele.style.visibility = "hidden");
// Or
const hide = (ele) => (ele.hidden = true);
在另一个元素之后插入一个元素#
const insertAfter = (ele, anotherEle) =>
anotherEle.parentNode.insertBefore(ele, anotherEle.nextSibling);
// Or
const insertAfter = (ele, anotherEle) =>
anotherEle.insertAdjacentElement("afterend", ele);
在其他元素之前插入一个元素#
const insertBefore = (ele, anotherEle) =>
anotherEle.parentNode.insertBefore(ele, anotherEle);
// Or
const insertBefore = (ele, anotherEle) =>
anotherEle.insertAdjacentElement("beforebegin", ele);
在元素后插入给定的HTML#
const insertHtmlAfter = (html, ele) => ele.insertAdjacentHTML("afterend", html);
在元素之前插入给定的HTML#
const insertHtmlBefore = (html, ele) =>
ele.insertAdjacentHTML("beforebegin", html);
重定向到另一个页面#
const goTo = (url) => (location.href = url);
重新加载当前页面#
const reload = () => location.reload();
// Or
const reload = () => (location.href = location.href);
替换元素#
const replace = (ele, newEle) => ele.parentNode.replaceChild(newEle, ele);
滚动到页面顶部#
const goToTop = () => window.scrollTo(0, 0);
序列化表单数据#
const serialize = (formEle) =>
Array.from(new FormData(formEle)).reduce(
(p, [k, v]) =>
Object.assign({}, p, {
[k]: p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v,
}),
{}
);
显示一个元素#
const show = (ele) => (ele.style.display = "");
从给定文本中剥离HTML#
const stripHtml = (html) =>
new DOMParser().parseFromString(html, "text/html").body.textContent || "";
切换元素#
const toggle = (ele) =>
(ele.style.display = ele.style.display === "none" ? "block" : "none");
// Or
const toggle = (ele) => (ele.hidden = !ele.hidden);
Date Time
将AM PM后缀添加到一个小时#
// `h` is an hour number between 0 and 23
const suffixAmPm = (h) =>
`${h % 12 === 0 ? 12 : h % 12}${h < 12 ? "am" : "pm"}`;
// Examples
suffixAmPm(0); // '12am'
suffixAmPm(5); // '5am'
suffixAmPm(12); // '12pm'
suffixAmPm(15); // '3pm'
suffixAmPm(23); // '11pm'
计算两个日期之间的差异天数#
const diffDays = (date, otherDate) =>
Math.ceil(Math.abs(date - otherDate) / (1000 * 60 * 60 * 24));
// Example
diffDays(new Date("2014-12-19"), new Date("2020-01-01")); // 1839
计算两个日期之间的月数#
const monthDiff = (startDate, endDate) =>
Math.max(
0,
(endDate.getFullYear() - startDate.getFullYear()) * 12 -
startDate.getMonth() +
endDate.getMonth()
);
// Example
monthDiff(new Date("2020-01-01"), new Date("2021-01-01")); // 12
比较两个日期#
// `a` and `b` are `Date` instances
const compare = (a, b) => a.getTime() > b.getTime();
// Example
compare(new Date("2020-03-30"), new Date("2020-01-01")); // true
将日期转换为YYYY-MM-DD格式#
// `date` is a `Date` object
const formatYmd = (date) => date.toISOString().slice(0, 10);
// Example
formatYmd(new Date()); // 2020-05-06
将秒转换为hh:mm:ss格式#
// `s` is number of seconds
const formatSeconds = (s) => new Date(s * 1000).toISOString().substr(11, 8);
// Or
const formatSeconds = (s) =>
new Date(s * 1000).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
// Or
const formatSeconds = (s) =>
[parseInt(s / 60 / 60), parseInt((s / 60) % 60), parseInt(s % 60)]
.join(":")
.replace(/\b(\d)\b/g, "0$1");
// Examples
formatSeconds(200); // 00:03:20
formatSeconds(500); // 00:08:20
从日期中提取年,月,日,小时,分钟,秒和毫秒#
// `date` is a `Date` object
const extract = (date) =>
date
.toISOString()
.split(/[^0-9]/)
.slice(0, -1);
// `extract` is an array of [year, month, day, hour, minute, second, millisecond]
格式化给定语言环境的日期#
// `date` is a `Date` object
// `locale` is a locale (en-US, pt-BR, for example)
const format = (date, locale) => new Intl.DateTimeFormat(locale).format(date);
// Example
format(new Date(), "pt-BR"); // 06/05/2020
获取当前日期的四分之一#
const getQuarter = (d = new Date()) => Math.ceil((d.getMonth() + 1) / 3);
以秒为单位获取当前时间戳#
const ts = () => Math.floor(new Date().getTime() / 1000);
从日期获取一年中的某天#
// `date` is a Date object
const dayOfYear = (date) =>
Math.floor(
(date - new Date(date.getFullYear(), 0, 0)) / (1000 * 60 * 60 * 24)
);
// Example
dayOfYear(new Date(2020, 04, 16)); // 137
获取日期月份中的第一个日期#
const getFirstDate = (d = new Date()) =>
new Date(d.getFullYear(), d.getMonth(), 1);
获取某月的最后一个日期#
const getLastDate = (d = new Date()) =>
new Date(d.getFullYear(), d.getMonth() + 1, 0);
获取日期的月份名称#
// `date` is a Date object
const getMonthName = (date) =>
[
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
" November",
"December",
][date.getMonth()];
获取给定月份的天数#
// `month` is zero-based index
const daysInMonth = (month, year) => new Date(year, month, 0).getDate();
获取时区字符串#
const getTimezone = () => Intl.DateTimeFormat().resolvedOptions().timeZone;
// Example
getTimezone(); // 'Asia/Saigon'
获取明天的日期#
const tomorrow = ((d) => new Date(d.setDate(d.getDate() + 1)))(new Date());
// Or
const tomorrow = new Date(new Date().valueOf() + 1000 * 60 * 60 * 24);
获取一年中的总天数#
const numberOfDays = (year) =>
(year % 4 === 0 && year % 100 !== 0) || year % 400 === 0 ? 366 : 365;
// Or
const numberOfDays = (year) =>
new Date(year, 1, 29).getDate() === 29 ? 366 : 365;
获取日期的工作日#
// `date` is a Date object
const getWeekday = (date) =>
[
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
][date.getDay()];
获取昨天的日期#
const yesterday = ((d) => new Date(d.setDate(d.getDate() - 1)))(new Date());
// Or
const yesterday = new Date(new Date().valueOf() - 1000 * 60 * 60 * 24);
初始化当前日期,但将时间设置为午夜#
const midnightOfToday = () => new Date(new Date().setHours(0, 0, 0, 0));
排序日期数组#
// `arr` is an array of `Date` items
const sortDescending = (arr) => arr.sort((a, b) => a.getTime() > b.getTime());
const sortAscending = (arr) => arr.sort((a, b) => a.getTime() < b.getTime());
Function
Box handler#
const boxHandler = x => ({ next: f => boxHandler(f(x)), done: f => f(x) });
// Example 1
const getPercentNumber = str => boxHandler(str).next(str => str.replace(/\%/, '')).next(str => parseFloat(str)).done(res => res * 0.01);
getPercentNumber('50%'); // 0.5
// Example 2
const getMoney = (price) => Number.parseFloat(price.replace(/\$/, ''));
const getPercent = (percent) => Number.parseFloat(percent.replace(/\%/)) * 0.01;
const getDiscountPrice = (price, discount) => boxHandler(getMoney(price)).done(cents => boxHandler(getPercent(discount)).next(save => cents - (cents * save))).done(res => res);
getDiscountPrice('$6.00', '20%'); // 4.8
检查值是否为函数#
const isFunction = (v) =>
[
"[object Function]",
"[object GeneratorFunction]",
"[object AsyncFunction]",
"[object Promise]",
].includes(Object.prototype.toString.call(v));
// Examples
isFunction(function () {}); // true
isFunction(function* () {}); // true
isFunction(async function () {}); // true
检查值是否是生成器函数#
const isGeneratorFunction = (v) =>
Object.prototype.toString.call(v) === "[object GeneratorFunction]";
// Examples
isGeneratorFunction(function () {}); // false
isGeneratorFunction(function* () {}); // true
检查值是否是异步函数#
const isAsyncFunction = (v) =>
Object.prototype.toString.call(v) === "[object AsyncFunction]";
// Examples
isAsyncFunction(function () {}); // false
isAsyncFunction(function* () {}); // false
isAsyncFunction(async function () {}); // true
从左到右编写功能#
// Compose functions from left to right
const pipe =
(...fns) =>
(x) =>
fns.reduce((y, f) => f(y), x);
// Example
const lowercase = (str) => str.toLowerCase();
const capitalize = (str) => `${str.charAt(0).toUpperCase()}${str.slice(1)}`;
const reverse = (str) => str.split("").reverse().join("");
const fn = pipe(lowercase, capitalize, reverse);
// We will execute `lowercase`, `capitalize` and `reverse` in order
fn("Hello World") === "dlrow olleH";
组合功能#
// Compose functions from right to left
const compose =
(...fns) =>
(x) =>
fns.reduceRight((y, f) => f(y), x);
// Example
const lowercase = (str) => str.toLowerCase();
const capitalize = (str) => `${str.charAt(0).toUpperCase()}${str.slice(1)}`;
const reverse = (str) => str.split("").reverse().join("");
const fn = compose(reverse, capitalize, lowercase);
// We will execute `lowercase`, `capitalize` and `reverse` in order
fn("Hello World") === "dlrow olleH";
创建一个接受单个参数的函数#
const unary = (fn) => (arg) => fn(arg);
// Example
["1", "2", "3", "4", "5"].map(unary(parseInt)); // [1, 2, 3, 4, 5]
创建一个空函数#
const noop = () => {};
// Or
const noop = Function();
// calling Function() might be detected as using eval by some security tools
Curry 的函数#
const curry = (fn, ...args) =>
fn.length <= args.length ? fn(...args) : curry.bind(null, fn, ...args);
// Example
const sum = (a, b, c) => a + b + c;
curry(sum)(1)(2)(3); // 6
curry(sum)(1, 2, 3); // 6
curry(sum, 1)(2, 3); // 6
curry(sum, 1)(2)(3); // 6
curry(sum, 1, 2)(3); // 6
curry(sum, 1, 2, 3); // 6
延迟函数的计算#
// returns a new version of `fn` that returns values as lazy evaluable
const thunkfy =
(fn) =>
(...args) =>
() =>
fn(...args);
// Example
const heavyComputation = (x) => doStuff(x);
const unnecessarySlow = manyThings
.map(heavyComputation)
.find((result) => result.criteria);
const probablyFaster = manyThings
.map(thunkfy(heavyComputation))
.find((thunk) => thunk().criteria);
一次执行一个函数#
const once = (fn) =>
(
(ran = false) =>
() =>
ran ? fn : ((ran = !ran), (fn = fn()))
)();
// Example
let n = 0;
const incOnce = once(() => ++n);
incOnce(); // n = 1
incOnce(); // n = 1
incOnce(); // n = 1
翻转函数的参数#
// Reverse the order of arguments
const flip =
(fn) =>
(...args) =>
fn(...args.reverse());
// For binary functions
const flip = (fn) => (b, a) => fn(a, b);
// Or for curried functions
const flip = (fn) => (b) => (a) => fn(a)(b);
// Example
const isParent = (parent, child) => parent.children.includes(child);
const isChild = flip(isParent);
一致函数#
const identity = (x) => x;
逻辑异或运算符#
// returns `true` if one of the arguments is truthy and the other is falsy
const xor = (a, b) => (a && !b) || (!a && b);
// Or
const xor = (a, b) => !(!a && !b) && !(a && b);
// Or
const xor = (a, b) => Boolean(!a ^ !b);
// Examples
xor(true, true); // false
xor(false, false); // false
xor(true, false); // true
xor(false, true); // true
Memoize的一个函数#
const memoize = (fn) =>
(
(cache = {}) =>
(arg) =>
cache[arg] || (cache[arg] = fn(arg))
)();
// Example
// Calculate Fibonacci numbers
const fibo = memoize((n) => (n <= 2 ? 1 : fibo(n - 1) + fibo(n - 2)));
fibo(1); // 1
fibo(2); // 1
fibo(3); // 2
fibo(4); // 3
fibo(5); // 5
fibo(6); // 8
部分应用函数#
const partial =
(fn, ...a) =>
(...b) =>
fn(...a, ...b);
// Example
const sum = (x, y) => x + y;
const inc = partial(sum, 1);
inc(9); // 10
Uncurry函数#
// `fn` is a curried function
// `n` is the depth of parameters
const uncurry =
(fn, n = 1) =>
(...args) =>
(
(acc) => (args) =>
args.reduce((x, y) => x(y), acc)
)(fn)(args.slice(0, n));
// Example
const sum = (a) => (b) => (c) => a + b + c;
uncurry(sum, 1)(1)(2)(3); // 6
uncurry(sum, 2)(1, 2)(3); // 6
uncurry(sum, 3)(1, 2, 3); // 6
Math
计算由两个点定义的直线的角度#
// In radians
const radiansAngle = (p1, p2) => Math.atan2(p2.y - p1.y, p2.x - p1.x);
// In degrees
const degreesAngle = (p1, p2) =>
(Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180) / Math.PI;
计算两点之间的距离#
const distance = (p1, p2) =>
Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
计算两点之间的中点#
const midpoint = (p1, p2) => [(p1.x + p2.x) / 2, (p1.y + p2.y) / 2];
检查点是否在矩形内#
const isInside = (point, rect) =>
point.x > rect.left &&
point.x < rect.right &&
point.y > rect.top &&
point.y < rect.bottom;
检查矩形是否包含其他矩形#
// Returns true if `a` contains `b`
// (x1, y1) and (x2, y2) are top-left and bottom-right corners
const contains = (a, b) =>
a.x1 <= b.x1 && a.y1 <= b.y1 && a.x2 >= b.x2 && a.y2 >= b.y2;
检查矩形是否与另一个矩形重叠#
// Returns true if `a` overlaps `b`
// (x1, y1) and (x2, y2) are top-left and bottom-right corners
const overlaps = (a, b) =>
(a.x1 < b.x2 && b.x1 < a.x2) || (a.y1 < b.y2 && b.y1 < a.y2);
将角度转换为弧度#
const degsToRads = (deg) => (deg * Math.PI) / 180.0;
将弧度转换为角度#
const radsToDegs = (rad) => (rad * 180) / Math.PI;
将数字四舍五入到一个给定值的最接近的倍数#
const roundNearest = (value, nearest) => Math.round(value / nearest) * nearest;
// Examples
roundNearest(100, 30); // 90
roundNearest(200, 30); // 210
roundNearest(200, 40); // 200
Misc
检查代码是否在NodeJS中运行#
const isNode =
typeof process !== "undefined" &&
process.versions != null &&
process.versions.node != null;
检查代码是否在浏览器中运行#
const isBrowser = typeof window === "object" && typeof document === "object";
清除所有Cookie#
const clearCookies = document.cookie
.split(";")
.forEach(
(c) =>
(document.cookie = c
.replace(/^ +/, "")
.replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`))
);
将3位数字的颜色转换为6位数字的颜色#
const toFullHexColor = (color) =>
`#${(color.startsWith("#") ? color.slice(1) : color)
.split("")
.map((c) => `${c}${c}`)
.join("")}`;
// Example
toFullHexColor("123"); // '#112233'
toFullHexColor("#123"); // '#112233'
toFullHexColor("#abc"); // '#aabbcc'
转换摄氏到华氏度#
const celsiusToFahrenheit = (celsius) => (celsius * 9) / 5 + 32;
// Examples
celsiusToFahrenheit(15); // 59
celsiusToFahrenheit(0); // 32
celsiusToFahrenheit(-20); // -4
将cookie转换为对象#
const cookies = document.cookie
.split(";")
.map((item) => item.split("="))
.reduce((acc, [k, v]) => (acc[k.trim().replace('"', "")] = v) && acc, {});
转换华氏到摄氏#
const fahrenheitToCelsius = (fahrenheit) => ((fahrenheit - 32) * 5) / 9;
// Examples
fahrenheitToCelsius(59); // 15
fahrenheitToCelsius(32); // 0
将十六进制转换为RGB#
const hexToRgb = (hex) =>
hex
.replace(
/^#?([a-f\d])([a-f\d])([a-f\d])$/i,
(_, r, g, b) => `#${r}${r}${g}${g}${b}${b}`
)
.substring(1)
.match(/.{2}/g)
.map((x) => parseInt(x, 16));
// Examples
hexToRgb("#00ffff"); // [0, 255, 255]
hexToRgb("#0ff"); // [0, 255, 255]
将RGB颜色转换为十六进制#
const rgbToHex = (red, green, blue) =>
`#${((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1)}`;
// Or
const rgbToHex = (red, green, blue) =>
`#${[red, green, blue].map((v) => v.toString(16).padStart(2, "0")).join("")}`;
// Example
rgbToHex(0, 255, 255); // '#00ffff'
将URL参数转换为对象#
const getUrlParams = (query) =>
Array.from(new URLSearchParams(query)).reduce(
(p, [k, v]) =>
Object.assign({}, p, {
[k]: p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v,
}),
{}
);
// Examples
getUrlParams(location.search); // Get the parameters of the current URL
getUrlParams("foo=Foo&bar=Bar"); // { foo: "Foo", bar: "Bar" }
// Duplicate key
getUrlParams("foo=Foo&foo=Fuzz&bar=Bar"); // { foo: ["Foo", "Fuzz"], bar: "Bar" }
解码JWT令牌#
const decode = (token) =>
decodeURIComponent(
atob(token.split(".")[1].replace("-", "+").replace("_", "/"))
.split("")
.map((c) => `%${("00" + c.charCodeAt(0).toString(16)).slice(-2)}`)
.join("")
);
// Example
decode(`
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0I
joxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
`);
// { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
检测暗模式#
const isDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
Easing functions#
// Some easing functions
// See https://gist.github.com/gre/1650294 and https://easings.net
const linear = (t) => t;
const easeInQuad = (t) => t * t;
const easeOutQuad = (t) => t * (2 - t);
const easeInOutQuad = (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t);
const easeInCubic = (t) => t * t * t;
const easeOutCubic = (t) => --t * t * t + 1;
const easeInOutCubic = (t) =>
t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
const easeInQuart = (t) => t * t * t * t;
const easeOutQuart = (t) => 1 - --t * t * t * t;
const easeInOutQuart = (t) =>
t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
const easeInQuint = (t) => t * t * t * t * t;
const easeOutQuint = (t) => 1 + --t * t * t * t * t;
const easeInOutQuint = (t) =>
t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
const easeInSine = (t) => 1 + Math.sin((Math.PI / 2) * t - Math.PI / 2);
const easeOutSine = (t) => Math.sin((Math.PI / 2) * t);
const easeInOutSine = (t) => (1 + Math.sin(Math.PI * t - Math.PI / 2)) / 2;
const easeInElastic = (t) => (0.04 - 0.04 / t) * Math.sin(25 * t) + 1;
const easeOutElastic = (t) => ((0.04 * t) / --t) * Math.sin(25 * t);
const easeInOutElastic = (t) =>
(t -= 0.5) < 0
? (0.02 + 0.01 / t) * Math.sin(50 * t)
: (0.02 - 0.01 / t) * Math.sin(50 * t) + 1;
模拟掷骰子#
const throwdice = () => ~~(Math.random() * 6) + 1;
// Examples
throwdice(); // 4
throwdice(); // 1
throwdice(); // 6
编码网址#
// `encodeURIComponent` doesn't encode -_.!~*'()
const encode = (url) =>
encodeURIComponent(url)
.replace(/!/g, "%21")
.replace(/~/g, "%7E")
.replace(/\*/g, "%2A")
.replace(/'/g, "%27")
.replace(/\(/g, "%28")
.replace(/\)/g, "%29")
.replace(/%20/g, "+");
生成唯一的增量ID#
const uid = (() => ((id = 0), () => id++))();
// Examples
uid(); // 0
uid(); // 1
uid(); // 2
uid(); // 3
获取第一个已定义且非null的参数#
const coalesce = (...args) =>
args.find((item) => item !== undefined && item !== null);
// Or
const coalesce = (...args) =>
args.find((item) => ![undefined, null].includes(item));
// Examples
coalesce(undefined, null, "helloworld", NaN); // 'helloworld'
获取Cookie的值#
const cookie = (name) =>
`; ${document.cookie}`.split(`; ${name}=`).pop().split(";").shift();
// Example
cookie("_ga"); // GA1.2.825309271.1581874719
从URL获取参数的值#
const getParam = (url, param) =>
new URLSearchParams(new URL(url).search).get(param);
// Example
getParam("http://domain.com?message=hello", "message"); // 'hello'
获取字符串中变量的类型#
const getTypeOf = (obj) =>
Object.prototype.toString.call(obj).match(/\[object (.*)\]/)[1];
// Examples
getTypeOf("hello world"); // String
getTypeOf(1000); // Number
getTypeOf(Infinity); // Number
getTypeOf(true); // Boolean
getTypeOf(Symbol()); // Symbol
getTypeOf(null); // Null
getTypeOf(undefined); // Undefined
getTypeOf({}); // Object
getTypeOf([]); // Array
getTypeOf(/[a-z]/g); // RegExp
getTypeOf(new Date(2021)); // Date
getTypeOf(new Error()); // Error
getTypeOf(function () {}); // Function
getTypeOf((a, b) => a + b); // Function
getTypeOf(async () => {}); // AsyncFunction
getTypeOf(document); // HTMLDocument
如果页面位于HTTP中,则将其重定向到HTTPS#
const redirectHttps = () =>
location.protocol === "https:"
? {}
: location.replace(`https://${location.href.split("//")[1]}`);
// Or
const redirectHttps = () =>
location.protocol === "https:" ? {} : (location.protocol = "https:");
按顺序运行Promises#
// `promises` is an array of `Promise`
const run = (promises) =>
promises.reduce(
(p, c) => p.then((rp) => c.then((rc) => [...rp, rc])),
Promise.resolve([])
);
// Example
run(promises).then((results) => {
// `results` is an array of promise results in the same order
});
交换两个变量#
[a, b] = [b, a];
// Or
a = [b, (b = a)][0];
// Or
a = ((x) => x)(b, (b = a));
// Or
// (only works with numbers)
a = b + ((b = a), 0);
a = b * ((b = a), 1);
等待一段时间#
const wait = async (milliseconds) =>
new Promise((resolve) => setTimeout(resolve, milliseconds));
Number
在数字后添加序数后缀#
// `n` is a position number
const addOrdinal = (n) =>
`${n}${["st", "nd", "rd"][((((n + 90) % 100) - 10) % 10) - 1] || "th"}`;
// Or
const addOrdinal = (n) => `${n}${[, "st", "nd", "rd"][/1?.$/.exec(n)] || "th"}`;
// Or
const addOrdinal = (n) =>
`${n}${[, "st", "nd", "rd"][(n % 100 >> 3) ^ 1 && n % 10] || "th"}`;
// Or
const addOrdinal = (n) =>
`${n}${
{ one: "st", two: "nd", few: "rd", other: "th" }[
new Intl.PluralRules("en", { type: "ordinal" }).select(n)
]
}`;
// Examples
addOrdinal(1); // '1st'
addOrdinal(2); // '2nd'
addOrdinal(3); // '3rd'
addOrdinal(11); // '11th'
addOrdinal(12); // '13th'
addOrdinal(13); // '13th'
计算斐波那契数#
const fibo = (n, memo = {}) =>
memo[n] || (n <= 2 ? 1 : (memo[n] = fibo(n - 1, memo) + fibo(n - 2, memo)));
// Examples
fibo(1); // 1
fibo(2); // 1
fibo(3); // 2
fibo(4); // 3
fibo(5); // 5
fibo(6); // 8
计算参数的平均值#
const average = (...args) => args.reduce((a, b) => a + b) / args.length;
// Example
average(1, 2, 3, 4); // 2.5
计算参数除法#
const division = (...args) => args.reduce((a, b) => a / b);
// Example
division(1, 2, 3, 4); // 0.04166666666666666
计算数字的阶乘#
const factorial = (n) => (n <= 1 ? 1 : n * factorial(n - 1));
// Examples
factorial(2); // 2
factorial(3); // 6
factorial(4); // 24
factorial(5); // 120
factorial(6); // 720
计算集合索引的mod#
const mod = (a, b) => ((a % b) + b) % b;
// Examples
mod(-1, 5); // 4
mod(3, 5); // 3
mod(6, 5); // 1
计算参数除法的余数#
const remainder = (...args) => args.reduce((a, b) => a % b);
// Example
remainder(1, 2, 3, 4); // 1
计算参数之和#
const sum = (...args) => args.reduce((a, b) => a + b);
// Example
sum(1, 2, 3, 4); // 10
将一个数字夹在两个值之间#
const clamp = (val, min = 0, max = 1) => Math.max(min, Math.min(max, val));
// Example
clamp(199, 10, 25); // 25
计算两个数字之间的最大公约数#
const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b));
// Example
gcd(10, 15); // 5
将数字转换为等效字符#
const toChars = (n) =>
`${n >= 26 ? toChars(Math.floor(n / 26) - 1) : ""}${
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n % 26]
}`;
// Examples
toChars(0); // A
toChars(1); // B
toChars(25); // Z
toChars(26); // AA
toChars(27); // AB
toChars(51); // AZ
toChars(701); // ZZ
toChars(702); // AAA
toChars(703); // AAB
将字符串转换为数字#
const toNumber = (str) => +str;
// Example
toNumber("42"); // 42
将十进制递归转换为二进制#
const decToBi = (num) =>
num === 0 ? 0 : (num % 2) + 10 * decToBi(~~(num / 2));
// Example
decToBi(10); //1010
从数字中获取数字数组#
const digitize = (n) => `${n}`.split("").map((v) => parseInt(v, 10));
// Or
const digitize = (n) => [...`${n}`].map((v) => parseInt(v, 10));
// Example
digitize(123); // [1, 2, 3]
相乘参数#
const mul = (...args) => args.reduce((a, b) => a * b);
// Example
mul(1, 2, 3, 4); // 24
前缀为零的整数#
const prefixWithZeros = (number, length) =>
(number / Math.pow(10, length)).toFixed(length).substr(2);
// Or
const prefixWithZeros = (number, length) =>
`${Array(length).join("0")}${number}`.slice(-length);
// Or
const prefixWithZeros = (number, length) =>
String(number).padStart(length, "0");
// Example
prefixWithZeros(42, 5); // '00042'
将数字四舍五入到给定的数字#
const round = (n, decimals = 0) =>
Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
// Examples
round(1.234567, 3); // 1.235
round(1.234567, 4); // 1.2346
减去参数#
const subtract = (...args) => args.reduce((a, b) => a - b);
// Example
subtract(1, 2, 3, 4); // -8
将数字截断为十进制#
const truncate = (n) => ~~n;
// Examples
truncate(25.198726354); // 25
truncate(-25.198726354); // -25
将数字截断到给定的小数位数而不四舍五入#
const toFixed = (n, fixed) =>
`${n}`.match(new RegExp(`^-?\\d+(?:\.\\d{0,${fixed}})?`))[0];
// Or
const toFixed = (n, fixed) => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed);
// Examples
toFixed(25.198726354, 1); // 25.1
toFixed(25.198726354, 2); // 25.19
toFixed(25.198726354, 3); // 25.198
toFixed(25.198726354, 4); // 25.1987
toFixed(25.198726354, 5); // 25.19872
toFixed(25.198726354, 6); // 25.198726
Object
检查多个对象是否相等#
const isEqual = (...objects) =>
objects.every((obj) => JSON.stringify(obj) === JSON.stringify(objects[0]));
// Examples
isEqual({ foo: "bar" }, { foo: "bar" }); // true
isEqual({ foo: "bar" }, { bar: "foo" }); // false
创建一个没有属性的空映射#
// `map` doesn't have any properties
const map = Object.create(null);
// The following `map` has `__proto__` property
// const map = {};
根据键和值对创建一个对象#
const toObj = (arr) => Object.fromEntries(arr);
// Or
const toObj = (arr) => arr.reduce((a, c) => ((a[c[0]] = c[1]), a), {});
// Example
toObj([
["a", 1],
["b", 2],
["c", 3],
]); // { a: 1, b: 2, c: 3 }
从对象数组中提取属性值#
const pluck = (objs, property) => objs.map((obj) => obj[property]);
// Example
pluck(
[
{ name: "John", age: 20 },
{ name: "Smith", age: 25 },
{ name: "Peter", age: 30 },
],
"name"
); // ['John', 'Smith', 'Peter']
获取对象给定路径的值#
const getValue = (path, obj) =>
path.split(".").reduce((acc, c) => acc && acc[c], obj);
// Example
getValue("a.b", { a: { b: "Hello World" } }); // 'Hello World';
不可更改地重命名对象键#
const renameKeys = (keysMap, obj) =>
Object.keys(obj).reduce(
(acc, key) => ({ ...acc, ...{ [keysMap[key] || key]: obj[key] } }),
{}
);
// Examples
const obj = { a: 1, b: 2, c: 3 };
const keysMap = { a: "d", b: "e", c: "f" };
renameKeys(keysMap, obj); // { d: 1, e: 2, f: 3 }
反转对象的键和值#
const invert = (obj) =>
Object.keys(obj).reduce((res, k) => Object.assign(res, { [obj[k]]: k }), {});
// Or
const invert = (obj) =>
Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]));
// Example
invert({ a: "1", b: "2", c: "3" }); // { 1: 'a', 2: 'b', 3: 'c' }
忽略对象的属性子集#
const omit = (obj, keys) =>
Object.keys(obj)
.filter((k) => !keys.includes(k))
.reduce((res, k) => Object.assign(res, { [k]: obj[k] }), {});
// Example
omit({ a: "1", b: "2", c: "3" }, ["a", "b"]); // { c: '3' }
选择一个对象的属性子集#
const pick = (obj, keys) =>
Object.keys(obj)
.filter((k) => keys.includes(k))
.reduce((res, k) => Object.assign(res, { [k]: obj[k] }), {});
// Example
pick({ a: "1", b: "2", c: "3" }, ["a", "b"]); // { a: '1', b: '2' }
从对象中删除所有null和未定义的属性#
const removeNullUndefined = (obj) =>
Object.entries(obj).reduce(
(a, [k, v]) => (v == null ? a : ((a[k] = v), a)),
{}
);
// Or
const removeNullUndefined = (obj) =>
Object.entries(obj)
.filter(([_, v]) => v != null)
.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
// Or
const removeNullUndefined = (obj) =>
Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));
// Example
removeNullUndefined({
foo: null,
bar: undefined,
fuzz: 42,
}); // { fuzz: 42 }
浅复制一个对象#
const shallowCopy = obj => Object.assign({}, obj);
// or
const shallowCopy = obj => {...obj};
按对象的属性对对象进行排序#
const sort = (obj) =>
Object.keys(obj)
.sort()
.reduce((p, c) => ((p[c] = obj[c]), p), {});
// Example
const colors = {
white: "#ffffff",
black: "#000000",
red: "#ff0000",
green: "#008000",
blue: "#0000ff",
};
sort(colors);
/*
{
black: '#000000',
blue: '#0000ff',
green: '#008000',
red: '#ff0000',
white: '#ffffff',
}
*/
Random
产生一个随机的布尔值#
const randomBoolean = () => Math.random() >= 0.5;
生成给定范围内的随机浮点数#
const randomFloat = (min, max) => Math.random() * (max - min) + min;
生成随机的十六进制颜色#
const randomColor = () =>
`#${Math.random().toString(16).slice(2, 8).padEnd(6, "0")}`;
// Or
const randomColor = () => `#${(~~(Math.random() * (1 << 24))).toString(16)}`;
生成给定范围内的随机整数#
const randomInteger = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
生成一个随机IP地址#
const randomIp = () =>
Array(4)
.fill(0)
.map((_, i) => Math.floor(Math.random() * 255) + (i === 0 ? 1 : 0))
.join(".");
// Example
randomIp(); // 175.89.174.131
产生随机信号#
const randomSign = () => (Math.random() >= 0.5 ? 1 : -1);
从给定字符生成随机字符串#
const generateString = (length, chars) =>
Array(length)
.fill("")
.map((v) => chars[Math.floor(Math.random() * chars.length)])
.join("");
// Example
generateString(
10,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
);
使用Node crypto模块生成随机字符串#
const randomStr = () => require("crypto").randomBytes(32).toString("hex");
生成给定长度的随机字符串#
const generateString = (length) =>
Array(length)
.fill("")
.map((v) => Math.random().toString(36).charAt(2))
.join("");
产生随机的UUID#
const uuid = (a) =>
a
? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16)
: ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid);
生成给定范围内的随机整数数组#
const randomArrayInRange = (min, max, n) =>
Array.from(
{ length: n },
() => Math.floor(Math.random() * (max - min + 1)) + min
);
// Example
randomArrayInRange(1, 100, 10); // [11, 82, 41, 35, 76, 83, 43, 15, 60, 54]
获取随机项目并将其从数组中删除#
const randomItem = (arr) => arr.splice((Math.random() * arr.length) | 0, 1);
// Example
const arr = [1, 3, 5, 7, 9];
randomItem(arr); // 7
// arr = [1, 3, 5, 9]
从数组中获取随机项#
const randomItem = (arr) => arr[(Math.random() * arr.length) | 0];
获取数组的随机项#
const randomItems = (arr, count) =>
arr
.concat()
.reduce(
(p, _, __, arr) =>
p[0] < count
? [
p[0] + 1,
p[1].concat(arr.splice((Math.random() * arr.length) | 0, 1)),
]
: p,
[0, []]
)[1];
// Examples
randomItems([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3); // [4, 8, 5]
randomItems(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"], 4); // ['e', 'c', 'h', 'j']
选择一个对象的随机属性#
const randomProp = (obj) =>
Object.keys(obj)[(Math.random() * Object.keys(obj).length) | 0];
// Example
const colors = {
aqua: "#00ffff",
azure: "#f0ffff",
beige: "#f5f5dc",
black: "#000000",
blue: "#0000ff",
brown: "#a52a2a",
cyan: "#00ffff",
darkblue: "#00008b",
darkcyan: "#008b8b",
darkgrey: "#a9a9a9",
darkgreen: "#006400",
darkkhaki: "#bdb76b",
darkmagenta: "#8b008b",
darkolivegreen: "#556b2f",
darkorange: "#ff8c00",
darkorchid: "#9932cc",
darkred: "#8b0000",
darksalmon: "#e9967a",
darkviolet: "#9400d3",
fuchsia: "#ff00ff",
gold: "#ffd700",
green: "#008000",
indigo: "#4b0082",
khaki: "#f0e68c",
lightblue: "#add8e6",
lightcyan: "#e0ffff",
lightgreen: "#90ee90",
lightgrey: "#d3d3d3",
lightpink: "#ffb6c1",
lightyellow: "#ffffe0",
lime: "#00ff00",
magenta: "#ff00ff",
maroon: "#800000",
navy: "#000080",
olive: "#808000",
orange: "#ffa500",
pink: "#ffc0cb",
purple: "#800080",
violet: "#800080",
red: "#ff0000",
silver: "#c0c0c0",
white: "#ffffff",
yellow: "#ffff00",
};
randomProp(colors); // 'red'
String
首字符串大写#
const capitalize = (str) => `${str.charAt(0).toUpperCase()}${str.slice(1)}`;
// Or
const capitalize = ([first, ...rest]) =>
`${first.toUpperCase()}${rest.join("")}`;
// Example
capitalize("hello world"); // 'Hello world'
检查路径是否相对#
const isRelative = (path) => !/^([a-z]+:)?[\\/]/i.test(path);
// Examples
isRelative("/foo/bar/baz"); // false
isRelative("C:\\foo\\bar\\baz"); // false
isRelative("foo/bar/baz.txt"); // true
isRelative("foo.md"); // true
检查字符串是否包含重复的字符序列#
const consistsRepeatedSubstring = (str) =>
`${str}${str}`.indexOf(str, 1) !== str.length;
// Example
consistsRepeatedSubstring("aa"); // true
consistsRepeatedSubstring("aaa"); // true
consistsRepeatedSubstring("ababab"); // true
consistsRepeatedSubstring("abc"); // false
检查字符串是否是回文#
const isPalindrome = (str) => str === str.split("").reverse().join("");
// Examples
isPalindrome("abc"); // false
isPalindrom("abcba"); // true
检查URL是否是绝对的#
const isAbsoluteUrl = (url) => /^[a-z][a-z0-9+.-]*:/.test(url);
// Example
isAbsoluteUrl("https://1loc.dev"); // true
isAbsoluteUrl("https://1loc.dev/foo/bar"); // true
isAbsoluteUrl("1loc.dev"); // false
isAbsoluteUrl("//1loc.dev"); // false
检查两个字符串是否拼字#
const areAnagram = (str1, str2) =>
str1.toLowerCase().split("").sort().join("") ===
str2.toLowerCase().split("").sort().join("");
// Examples
areAnagram("listen", "silent"); // true
areAnagram("they see", "the eyes"); // true
areAnagram("node", "deno"); // true
将一个字母转换为关联的表情符号#
const letterToEmoji = (c) =>
String.fromCodePoint(c.toLowerCase().charCodeAt() + 127365);
// Examples
letterToEmoji("a"); // 🇦
letterToEmoji("b"); // 🇧
将字符串转换为camelCase#
const toCamelCase = (str) =>
str.trim().replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""));
// Examples
toCamelCase("background-color"); // backgroundColor
toCamelCase("-webkit-scrollbar-thumb"); // WebkitScrollbarThumb
toCamelCase("_hello_world"); // HelloWorld
toCamelCase("hello_world"); // helloWorld
将字符串转换为PascalCase#
const toPascalCase = (str) =>
(str.match(/[a-zA-Z0-9]+/g) || [])
.map((w) => `${w.charAt(0).toUpperCase()}${w.slice(1)}`)
.join("");
// Examples
toPascalCase("hello world"); // 'HelloWorld'
toPascalCase("hello.world"); // 'HelloWorld'
toPascalCase("foo_bar-baz"); // FooBarBaz
将字符串转换为URL段#
const slugify = (string) =>
string
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/[^\w-]+/g, "");
// Example
slugify("Chapter One: Once upon a time..."); // 'chapter-one-once-upon-a-time'
将Windows文件路径转换为Unix路径#
const toUnixPath = (path) =>
path.replace(/[\\/]+/g, "/").replace(/^([a-zA-Z]+:|\.\/)/, "");
// Examples
toUnixPath("./foo/bar/baz"); // foo/bar/baz
toUnixPath("C:\\foo\\bar\\baz"); // /foo/bar/baz
将camelCase转换为kebab-case,反之亦然#
const kebabToCamel = (str) => str.replace(/-./g, (m) => m.toUpperCase()[1]);
const camelToKebab = (str) =>
str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
// Examples
kebabToCamel("background-color"); // 'backgroundColor'
camelToKebab("backgroundColor"); // 'background-color'
将snake_case转换为camelCase#
const snakeToCamel = (str) =>
str.toLowerCase().replace(/(_\w)/g, (m) => m.toUpperCase().substr(1));
// Example
snakeToCamel("HELLO_world"); // 'helloWorld'
将Excel列的名称转换为数字#
const getIndex = (col) =>
col.split("").reduce((prev, next) => prev * 26 + parseInt(next, 36) - 9, 0);
// Examples
getIndex("A"); // 1
getIndex("B"); // 2
getIndex("C"); // 3
getIndex("Z"); // 26
getIndex("AA"); // 27
getIndex("AB"); // 28
getIndex("AC"); // 29
getIndex("AZ"); // 52
getIndex("AAA"); // 703
getIndex("AAB"); // 704
计算字符串中字符的出现#
const countOccurrences = (str, char) =>
[...str].reduce((a, v) => (v === char ? a + 1 : a), 0);
// Or
const countOccurrences = (str, char) =>
str.split("").reduce((a, v) => (v === char ? a + 1 : a), 0);
// Or
const countOccurrences = (str, char) =>
[...str].filter((item) => item === char).length;
// Or
const countOccurrences = (str, char) =>
str.split("").filter((item) => item === char).length;
// Examples
countOccurrences("a.b.c.d.e", "."); // 4
字符串去大写#
const decapitalize = (str) => `${str.charAt(0).toLowerCase()}${str.slice(1)}`;
// Or
const decapitalize = ([first, ...rest]) =>
`${first.toLowerCase()}${rest.join("")}`;
// Example
decapitalize("Hello world"); // 'hello world'
转义HTML特殊字符#
const escape = (str) =>
str
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/'/g, "&#39;")
.replace(/"/g, "&quot;");
// Or
const escape = (str) =>
str.replace(
/[&<>"']/g,
(m) =>
({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[
m
])
);
生成字符串的哈希#
const hash = (str) =>
str
.split("")
.reduce((prev, curr) => (Math.imul(31, prev) + curr.charCodeAt(0)) | 0, 0);
// Or
const hash = (str) =>
str
.split("")
.reduce((prev, curr) => ((prev << 5) - prev + curr.charCodeAt(0)) | 0, 0);
// Example
hash("hello"); // 99162322
获取不带任何参数的基本URL#
const baseUrl = (url) =>
url.indexOf("?") === -1 ? url : url.slice(0, url.indexOf("?"));
// Or
// Note that `includes` isn't supported in IE 11
const baseUrl = (url) =>
url.includes("?") ? url.slice(0, url.indexOf("?")) : url;
// Example
baseUrl("https://domain.com/path/sub/path?foo=bar&hello=world"); // 'https://domain.com/path/sub/path'
从文件名获取文件扩展名#
const ext = (fileName) => fileName.split(".").pop();
从URL获取文件名#
const fileName = (url) => url.substring(url.lastIndexOf("/") + 1);
// Example
fileName("http://domain.com/path/to/document.pdf"); // 'document.pdf'
获取字符串的长度(以字节为单位)#
const bytes = (str) => new Blob([str]).size;
// Examples
bytes("hello world"); // 11
bytes("🎉"); // 4
获取字符串中的字符数#
const characterCount = (str, char) => str.split(char).length - 1;
// Or
const characterCount = (str, char) =>
str.replace(new RegExp(String.raw`[^${char}]`, "g"), "").length;
// Examples
characterCount("192.168.1.1", "."); // 3
characterCount("star wars", "s"); // 2
使字符串的第一个字符小写#
const lowercaseFirst = (str) => `${str.charAt(0).toLowerCase()}${str.slice(1)}`;
// Example
lowercaseFirst("Hello World"); // 'hello World'
标准化文件路径斜杠#
const normalizePath = (path) => path.replace(/[\\/]+/g, "/");
// Example
normalizePath("\\foo\\bar\\baz\\"); // /foo/bar/baz/
normalizePath(".//foo//bar///////baz/"); // ./foo/bar/baz/
从字符串中删除空格#
const removeSpaces = (str) => str.replace(/\s/g, "");
// Example
removeSpaces("hel lo wor ld"); // 'helloworld'
重复一个字符串#
const repeat = (str, numberOfTimes) => str.repeat(numberOfTimes);
// Or
const repeat = (str, numberOfTimes) => Array(numberOfTimes + 1).join(str);
将所有换行符替换为br元素#
const nl2br = (str) => str.replace(new RegExp("\r?\n", "g"), "<br>");
// In React
str.split("\n").map((item, index) => (
<React.Fragment key={index}>
{item}
<br />
</React.Fragment>
));
用一个空格替换多个空格#
// Replace spaces, tabs and new line characters
const replaceSpaces = (str) => str.replace(/\s\s+/g, " ");
// Only replace spaces
const replaceOnlySpaces = (str) => str.replace(/ +/g, " ");
// Example
replaceSpaces("this\n is \ta \rmessage"); // 'this is a message'
将字符串的第一个给定字符数替换为另一个字符#
const mask = (str, num, mask) =>
`${str}`.slice(num).padStart(`${str}`.length, mask);
// Example
mask(1234567890, 3, "*"); // ***4567890
反转字符串#
const reverse = (str) => str.split("").reverse().join("");
// Or
const reverse = (str) => [...str].reverse().join("");
// Or
const reverse = (str) =>
str.split("").reduce((rev, char) => `${char}${rev}`, "");
// Or
const reverse = (str) =>
str === "" ? "" : `${reverse(str.substr(1))}${str.charAt(0)}`;
// Example
reverse("hello world"); // 'dlrow olleh'
按字母顺序对字符串的字符进行排序#
const sort = (str) =>
str
.split("")
.sort((a, b) => a.localeCompare(b))
.join("");
// Example
sort("hello world"); // dehllloorw
从字符串中删除ANSI代码#
const stripAnsiCodes = (str) =>
str.replace(
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
""
);
// Example
stripAnsiCodes("\u001B[4mcake\u001B[0m"); // 'cake'
stripAnsiCodes(
"\u001B[0m\u001B[4m\u001B[42m\u001B[31mfoo\u001B[39m\u001B[49m\u001B[24mfoo\u001B[0m"
); // 'foofoo'
交换字符串中的字符大小写#
const swapCase = (str) =>
str
.split("")
.map((c) => (c === c.toLowerCase() ? c.toUpperCase() : c.toLowerCase()))
.join("");
// Example
swapCase("Hello World"); // 'hELLO wORLD'
在字符串的开始和结束处修剪斜杠#
const trimSlashes = (str) => str.replace(/^\/+|\/+$/g, "");
// Or
const trimSlashes = (str) => str.split("/").filter(Boolean).join("/");
// Example
trimSlashes("//hello/world///"); // hello/world
削减一些字符#
const trim = (str, char) => str.split(char).filter(Boolean).join();
// Examples
trim("/hello world//", "/"); // hello world
trim('"hello world"', '"'); // hello world
trim(" hello world ", " "); // hello world
从文件名中删除文件扩展名#
const trimExt = (fileName) =>
fileName.indexOf(".") === -1
? fileName
: fileName.split(".").slice(0, -1).join(".");
// Examples
trimExt("document"); // document
trimExt("document.pdf"); // document
trimExt("document.2020.pdf"); // document.2020
在完整单词处截断字符串#
const truncate = (str, max, suffix) =>
str.length < max
? str
: `${str.substr(
0,
str.substr(0, max - suffix.length).lastIndexOf(" ")
)}${suffix}`;
// Example
truncate("This is a long message", 20, "..."); // 'This is a long...'
取消转义HTML特殊字符#
const unescape = (str) =>
str
.replace(/&amp;/g, "&")
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/*39;/g, "'")
.replace(/&quot;/g, '"');
将字符串中每个单词的第一个字符大写#
const uppercaseWords = (str) =>
str
.split(" ")
.map((w) => `${w.charAt(0).toUpperCase()}${w.slice(1)}`)
.join(" ");
// Or
const uppercaseWords = (str) =>
str.replace(/^(.)|\s+(.)/g, (c) => c.toUpperCase());
// Example
uppercaseWords("hello world"); // 'Hello World'
Validator
检查日期是否是工作日#
// `date` is a Date object
const isWeekday = (date = new Date()) => date.getDay() % 6 !== 0;
检查日期是否是周末#
// `date` is a Date object
const isWeekend = (date = new Date()) => date.getDay() % 6 === 0;
检查日期是否在两个日期之间#
// `min`, `max` and `date` are `Date` instances
const isBetween = (date, min, max) =>
date.getTime() >= min.getTime() && date.getTime() <= max.getTime();
检查日期是否是今天#
// `date` is a Date object
const isToday = (date) =>
date.toISOString().slice(0, 10) === new Date().toISOString().slice(0, 10);
检查日期是否在当年#
// `date` is a Date object
const isCurrentYear = (date) =>
date.getUTCFullYear() === new Date().getUTCFullYear();
检查平面数组是否有重复值#
const hasDuplicateValues = (arr) => new Set(arr).size !== arr.length;
// Examples
hasDuplicateValues(["h", "e", "l", "l", "o"]); // true
hasDuplicateValues(["w", "o", "r", "d"]); // false
检查给定的整数是否是质数#
const isPrime = (num) =>
num > 1 &&
Array(Math.floor(Math.sqrt(num)) - 1)
.fill(0)
.map((_, i) => i + 2)
.every((i) => num % i !== 0);
检查数字是否为2的幂#
const isPowerOfTwo = (number) => (number & (number - 1)) === 0;
// Examples
isPowerOfTwo(256); // true
isPowerOfTwo(129); // false
检查数字是否为偶数#
const isEven = (number) => number % 2 === 0;
// Or
const isEven = (number) => (number & 1) === 0;
// Or
const isEven = (number) => !(number & 1);
// Or
const isEven = (number) => Number.isInteger(number / 2);
// Examples
isEven(1); // false
isEven(2); // true
检查数字是否在给定范围内#
const inRange = (num, a, b, threshold = 0) =>
Math.min(a, b) - threshold <= num && num <= Math.max(a, b) + threshold;
// Example
inRange(10, 5, 15); // true
inRange(10, 5, 6); // false
inRange(10, 15, 5); // true
inRange(-10, -5, -15); // true
检查数字是否为负#
const isNegative = (number) => Math.sign(number) === -1;
// Or
const isNegative = (number) => number < 0;
// Examples
isNegative(-3); // true
isNegative(8); // false
检查数字是否为奇数#
const isOdd = (number) => number % 2 !== 0;
// Or
const isOdd = (number) => !!(number & 1);
// Or
const isOdd = (number) => !Number.isInteger(number / 2);
// Examples
isOdd(1); // true
isOdd(2); // false
检查数字是否为正#
const isPositive = (number) => Math.sign(number) === 1;
// Examples
isPositive(3); // true
isPositive(-8); // false
检查字符串是否包含小写字符#
const containsLowerCase = (str) => str !== str.toUpperCase();
// Examples
containsLowerCase("Hello World"); // true
containsLowerCase("HELLO WORLD"); // false
检查字符串是否仅包含ASCII字符#
const isAscii = (str) => /^[\x00-\x7F]+$/.test(str);
检查字符串是否仅包含数字#
const isNumeric = (str) => !/[^0-9]/.test(str);
// Examples
isNumeric(2); // true
isNumeric("23"); // true
isNumeric("00123"); // true
isNumeric("1.23"); // false
isNumeric("-Infinity"); // false
isNumeric("Infinity"); // false
isNumeric("NaN"); // false
检查字符串是否仅包含字母和数字#
const isAlphanumeric = (str) => /^[0-9A-Z]+$/i.test(str);
// Examples
isAlphanumeric("helloworld"); // true
isAlphanumeric("HelloWorld"); // true
isAlphanumeric("hello world"); // false
isAlphanumeric("hello123"); // true
isAlphanumeric("hello 123"); // false
检查字符串是否仅包含字母#
const isAlpha = (str) => /^[A-Z]+$/i.test(str);
// Examples
isAlpha("helloworld"); // true
isAlpha("HelloWorld"); // true
isAlpha("hello world"); // false
isAlpha("0123456789"); // false
检查字符串是否包含大写字符#
const containsUpperCase = (str) => str !== str.toLowerCase();
// Examples
containsUpperCase("Hello World"); // true
containsUpperCase("hello world"); // false
检查字符串是否包含空格#
const containsWhitespace = (str) => (str) => /\s/.test(str);
// Example
containsWhitespace("hello world"); // true
检查字符串是否为十六进制颜色#
const isHexColor = (color) =>
/^#([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i.test(color);
// Examples
isHexColor("#012"); // true
isHexColor("#A1B2C3"); // true
isHexColor("012"); // false
isHexColor("#GHIJKL"); // false
检查字符串是否为十六进制数字#
const isHexadecimal = (str) => /^[A-F0-9]+$/i.test(str);
// Or
const isHexadecimal = (str) =>
str.split("").every((c) => "0123456789ABCDEFabcdef".indexOf(c) !== -1);
// Examples
isHexadecimal("123"); // true
isHexadecimal("A1B2C3"); // true
isHexadecimal("#123"); // false
检查字符串是否为MongoDB ObjectId#
const isMongoId = (str) => str.length === 24 && /^[A-F0-9]+$/i.test(str);
// Or
const isMongoId = (str) =>
str.length === 24 &&
str.split("").every((c) => "0123456789ABCDEFabcdef".indexOf(c) !== -1);
检查字符串是否为八进制数字#
const isOctal = (str) => /^(0o)?[0-7]+$/i.test(str);
检查字符串是否为小写#
const isLowerCase = (str) => str === str.toLowerCase();
检查字符串是否为大写#
const isUpperCase = (str) => str === str.toUpperCase();
检查值是否是业务标识符代码#
const isBIC = (value) =>
/^[a-zA-Z]{6}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?$/.test(value);
检查值是否为数字#
const isNumber = (value) => !isNaN(parseFloat(value)) && isFinite(value);
检查值是否为普通对象#
const isPlainObject = (v) =>
!!v &&
typeof v === "object" &&
(v.__proto__ === null || v.__proto__ === Object.prototype);
// Examples
isPlainObject(null); // false
isPlainObject("hello world"); // false
isPlainObject([]); // false
isPlainObject(Object.create(null)); // false
isPlainObject(function () {}); // false
isPlainObject({}); // true
isPlainObject({ a: "1", b: "2" }); // true
检查值是否为正则表达式#
const isRegExp = (value) =>
Object.prototype.toString.call(value) === "[object RegExp]";
检查值是否为字符串#
const isString = (value) =>
Object.prototype.toString.call(value) === "[object String]";
// Examples
isString("hello world"); // true
isString(new String("hello world")); // true
isString(10); // false
检查值是否是对象#
const isObject = (v) => v !== null && typeof v === "object";
// Examples
isObject(null); // false
isObject("hello world"); // false
isObject({}); // true
isObject([]); // true
检查值是否为base32编码#
const isBase32 = (value) =>
value.length % 8 === 0 && /^[A-Z2-7]+=*$/.test(value);
检查值是否为base58编码#
// It doesn't accept the I, O, l characters
const isBase58 = (value) => /^[A-HJ-NP-Za-km-z1-9]*$/.test(value);
检查值是否为base64编码#
const isBase64 = (value) =>
/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(
value
);
检查值是否为零#
const isNil = (value) => value == null;
检查一年是否为leap年#
const isLeapYear = (year) =>
(year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
// Or
// Get the number of days in February
const isLeapYear = (year) => new Date(year, 1, 29).getDate() === 29;
检查所有数组元素是否等于给定值#
const isEqual = (arr, value) => arr.every((item) => item === value);
// Or
// Ends earlier for false arrays
const isEqual = (arr, value) => !arr.some((item) => item !== value);
// Examples
isEqual(["foo", "foo"], "foo"); // true
isEqual(["foo", "bar"], "foo"); // false
isEqual(["bar", "bar"], "foo"); // false
检查数组中的所有项是否相等#
const areEqual = (arr) =>
arr.length > 0 && arr.every((item) => item === arr[0]);
// Or
const areEqual = (arr) => new Set(arr).size === 1;
// Examples
areEqual([1, 2, 3, 4]); // false
areEqual(["hello", "hello", "hello"]); // true
检查数组是否包含与某些条件匹配的值#
const contains = (arr, criteria) => arr.some((v) => criteria(v));
// Or
const contains = (arr, criteria) => arr.some(criteria);
// Or
const contains = (arr, criteria) => arr.filter(criteria).length > 0;
// Examples
contains([10, 20, 30], (v) => v > 25); // true
contains([10, 20, 30], (v) => v > 100 || v < 15); // true
contains([10, 20, 30], (v) => v > 100); // false
检查数组是否为空#
const isNotEmpty = (arr) => Array.isArray(arr) && Object.keys(arr).length > 0;
// Examples
isNotEmpty([]); // false
isNotEmpty([1, 2, 3]); // true
检查一个数组是否是其他数组的子集#
// Check if `b` is subset of `a`
const isSubset = (a, b) => new Set(b).size === new Set(b.concat(a)).size;
// Or
const isSubset = (a, b) => b.join("|").includes(a.join("|"));
// Examples
isSubset([1, 2], [1, 2, 3, 4]); // true
isSubset([1, 2, 5], [1, 2, 3, 4]); // false
isSubset([6], [1, 2, 3, 4]); // false
检查对象是否为Promise#
const isPromise = (obj) =>
!!obj &&
(typeof obj === "object" || typeof obj === "function") &&
typeof obj.then === "function";
检查对象是否为数组#
const isArray = (obj) => Array.isArray(obj);
检查对象是否为空#
const isEmpty = (obj) =>
Reflect.ownKeys(obj).length === 0 && obj.constructor === Object;
// Or for enumerable property names only
const isEmpty = (obj) => JSON.stringify(obj) === "{}";
验证公历日期#
// `m`: the month (zero-based index)
// `d`: the day
// `y`: the year
const isValidDate = (m, d, y) =>
0 <= m &&
m <= 11 &&
0 < y &&
y < 32768 &&
0 < d &&
d <= new Date(y, m, 0).getDate();