String 类
返回字符串的字节长度
此代码返回字符串的字节长度。这里用到了Blob对象,Blob(Binary Large Object)对象代表了一段二进制数据,提供了一系列操作接口。其他操作二进制数据的API(比如File对象),都是建立在Blob对象基础上的,继承了它的属性和方法。生成Blob对象有两种方法:一种是使用Blob构造函数,另一种是对现有的Blob对象使用slice方法切出一部分。
const byteSize = str => new Blob([str]).size;
byteSize('😀'); // 4
byteSize('Hello World'); // 11
字符串的首字母转成大写
将字符串的首字母转成大写,这里主要运用到了ES6的展开语法在数组中的运用。
const capitalize = ([first, ...rest]) =>
first.toUpperCase() + rest.join('');
capitalize('fooBar'); // 'FooBar'
capitalize('fooBar', true); // 'FooBar'
字符串的首字母转换成小写字母
将字符串的首字母转换成小写字母
const decapitalize = ([first, ...rest]) =>
first.toLowerCase() + rest.join('')
decapitalize('FooBar'); // 'fooBar'
一个句子中每个单词首字母转换成大写
将一个句子中每个单词首字母转换成大写字母,这里中要运用了正则表达式进行替换。
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
capitalizeEveryWord('hello world!'); // 'Hello World!'
Number 类
截断数字
将小数点后的某些数字截断而不取四舍五入
const toFixed = (n, fixed) => `${n}`.match(new RegExp(`^-?\d+(?:.\d{0,${fixed}})?`))[0]
toFixed(10.255, 2) // 10.25
四舍五入
将小数点后的某些数字截断,并取四舍五入
const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`)
round(10.255, 2) // 10.26
补零
当你需要在一个数字num不足len位数的时候前面补零操作
const replenishZero = (num, len, zero = 0) => num.toString().padStart(len, zero)
replenishZero(8, 2) // 08
千分符
/*
* @name: milliFormat
* @description: 千位符并保留2位小数,将传入数据转换为字符串,并清除字符串中非数字与.的字符,按数字格式补全字符串
* @param: {Number,String} 需要转换的值
* @return: {String} 转换后数字
* @example: milliFormat("1023.1") => 1,023.10
*/
function milliFormat(s) {
s = String(s)
s = s.replace(/^(\d*)$/, '$1.')
s = (s + '00').replace(/(\d*\.\d\d)\d*/, '$1')
s = s.replace('.', ',')
var re = /(\d)(\d{3},)/
while (re.test(s)) {
s = s.replace(re, '$1,$2')
}
s = s.replace(/,(\d\d)$/, '.$1')
return s.replace(/^\./, '0.')
}
/*
* @name: commafyback
* @description: 去千位符
* @param: str {String} 需要转换的值
* @return: {String} 转换后数字
* @example: commafyback("102,123.18") => 102123.18
*/
function commafyback(str) {
var x = String(str).split(',')
return x.join('')
}
检查两个数字是否近似相等
此代码示例检查两个数字是否近似相等,差异值可以通过传参的形式进行设置
const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
approximatelyEqual(Math.PI / 2.0, 1.5708); // true
计算平均数
此段代码返回两个或多个数的平均数。
const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
average(...[1, 2, 3]); // 2
average(1, 2, 3); // 2
对象计算平均值
一个 map()函数和 reduce()函数结合的例子,此函数先通过 map() 函数将对象转换成数组,然后在调用reduce()函数进行累加,然后根据数组长度返回平均值。
const averageBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
arr.length;
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5
标准的度数转换成弧度
此段代码将标准的度数,转换成弧度。
const degreesToRads = deg => (deg * Math.PI) / 180.0;
degreesToRads(90.0); // ~1.5708
数字拆分成单个数字组成的数组
将输入的数字拆分成单个数字组成的数组。
const digitize = n => [...`${n}`].map(i => parseInt(i));
digitize(431); // [4, 3, 1]
计算两点之间的距离
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
distance(1, 1, 2, 3); // 2.23606797749979
区间随机数
const randomUniform(min, max)=> Math.round(Math.random() * (max - min) + min)
Array类
统计数组中某个值出现的次数
统计数组中某个值出现的次数
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3
是否满足数组所有条件
如果数组所有元素满足函数条件,则返回true。调用时,如果省略第二个参数,则默认传递布尔值。
const all = (arr, fn = Boolean) => arr.every(fn);
all([4, 2, 3], x => x > 1); // true
all([1, 2, 3]); // true
生成数组
// 方法一
const createArr = (n) => Array.from(new Array(n), (v, i) => i)
const arr = createArr(100) // 0 - 99 数组
// 方法二
const createArr = (n) => new Array(n).fill(0).map((v, i) => i)
createArr(100) // 0 - 99数组
计算数组极值
// 最小
function smallest(array){
return Math.min.apply(Math, array);
}
// 最大
function largest(array){
return Math.max.apply(Math, array);
}
打乱数组
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
list.sort(() => Math.random() - 0.5);
类数组转为数组
Array.prototype.slice.call(arguments);
// or
[...arguments]
数组数据去重
// 基础去重
const removeDuplicates = list => [...new Set(list)]
removeDuplicates([0, 0, 2, 4, 5]) // [0,2,4,5]
// 根据唯一值对数组进行去重
const duplicateById = list => [...list.reduce((prev, cur) => prev.set(cur.id, cur), new Map()).values()]
duplicateById([{id: 1, name: 'jack'}, {id: 2, name: 'rose'}, {id: 1, name: 'jack'}])
// [{id: 1, name: 'jack'}, {id: 2, name: 'rose'}]
多数组取交集
当你需要取多个数组中的交集
const intersection = (a, ...arr) => [...new Set(a)].filter((v) => arr.every((b) => b.includes(v)))
intersection([1, 2, 3, 4], [2, 3, 4, 7, 8], [1, 3, 4, 9])
// [3, 4]
查找最大值索引
但你需要找到一个数组中的最大值的索引
const indexOfMax = (arr) => arr.reduce((prev, curr, i, a) => (curr > a[prev] ? i : prev), 0);
indexOfMax([1, 3, 9, 7, 5]); // 2
找到最接近的数值
当你需要在一个数组中找到一个最接近的值
const closest = (arr, n) => arr.reduce((prev, curr) => (Math.abs(curr - n) < Math.abs(prev - n) ? curr : prev))
closest([29, 87, 8, 78, 97, 20, 75, 33, 24, 17], 50) // 33
递归数组降为一维
// 第一
let children = [1, [2, 3], [4, [5, 6, [7, 8]]], [9, 10]];
function simpleNormalizeChildren(children) {
for (let i = 0; i < children.length; i++) {
if (Array.isArray(children[i])) {
children = Array.prototype.concat.apply([], children);
simpleNormalizeChildren(children)
}
}
return children;
}
console.log(simpleNormalizeChildren(children)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10。
// 第二
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]
// 按照指定数组的深度,将嵌套数组进行展平。
const flatten = (arr, depth = 1) =>
arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
判断数组中的元素是否都相等
判断数组中的元素是否都相等
const allEqual = arr => arr.every(val => val === arr[0]);
allEqual([1, 2, 3, 4, 5, 6]); // false
allEqual([1, 1, 1, 1]); // true
数组转CSV
此段代码将没有逗号或双引号的元素转换成带有逗号分隔符的字符串即CSV格式识别的形式。
const arrayToCSV = (arr, delimiter = ',') =>
arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n');
arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"'
arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"'
将非数值的值转换成数组对象
此段代码将非数值的值转换成数组对象。
const castArray = val => (Array.isArray(val) ? val : [val]);
castArray('foo'); // ['foo']
castArray([1]); // [1]
移除值为"假"的内容
将数组中移除值为 假值 的内容。
const compact = arr => arr.filter(Boolean);
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]);
// [ 1, 2, 3, 'a', 's', 34 ]
查找两个给定数组的差异
此段代码查找两个给定数组的差异,查找出前者数组在后者数组中不存在元素。
const difference = (a, b) => {
const s = new Set(b);
return a.filter(x => !s.has(x));
};
difference([1, 2, 3], [1, 2, 4]); // [3]
逻辑筛选需要对比差异的数组
此段代码按照给定函数逻辑筛选需要对比差异的数组,查找出前者数组在后者数组中不存在元素。.
const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b));
// [1, 1.2]
两个数组元素之间的交集
const intersection = (a, b) => {
const s = new Set(b);
return a.filter(x => s.has(x));
};
intersection([1, 2, 3], [4, 3, 2]); // [2, 3]
// 按照给定的函数处理需要对比的数组元素,然后根据处理后的数组,找出交集,最后从第一个数组中将对应的元素输出。
const intersectionBy = (a, b, fn) => {
const s = new Set(b.map(fn));
return a.filter(x => s.has(fn(x)));
};
intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1]
// 按照给定的函数对比两个数组的差异,然后找出交集,最后从第一个数组中将对应的元素输出。
const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]
Object 类
删除无效属性
const removeNullUndefined = (obj) => Object.entries(obj).reduce((a, [k, v]) => (v == null ? a : ((a[k] = v), a)), {});
removeNullUndefined({name: '', age: undefined, sex: null}) // { name: '' }。
去重对象的属性
去重对象的属性,如果对象中含有重复的属性,以前面的为准。
const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);
defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 }
给定函数迭代对象
此段代码按照给定的函数条件,支持三个参数作为输入(值、键、对象本身),进行迭代对象。
const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1
第一个对象是否包含与第二个对象相同的属性与值
此函数功能用于比较两个对象,以确定第一个对象是否包含与第二个对象相同的属性与值。
const matches = (obj, source) =>
Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);
matches({ age: 25, hair: 'long', beard: true }, { hair: 'long', beard: true }); // true
matches({ hair: 'long', beard: true }, { age: 25, hair: 'long', beard: true }); // false
Function 类
使用可选链进行函数调用
function doSomething(onContent, onError) {
try {
// ... do something with the data
}
catch (err) {
onError?.(err.message); // 如果onError是undefined也不会有异常
}
}
函数值执行一次
function once (fn) {
// 利用闭包判断函数是否执行过
let called = false
return function () {
if (!called) {
called = true
fn.apply(this, arguments)
}
}
}
防抖方法
/**
* 防抖
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
let timeout;
function Debounce(func, wait = 3000, immediate = true) {
// 清除定时器
if (timeout !== null) clearTimeout(timeout);
// 立即执行,此类情况一般用不到
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function() {
timeout = null;
}, wait);
if (callNow) typeof func === 'function' && func();
} else {
// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
timeout = setTimeout(function() {
typeof func === 'function' && func();
}, wait);
}
}
Debounce(()=>console.log(1));
延迟函数的调用
延迟函数的调用,即异步调用函数。
const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'
Date 类
是否今天
function isToday(dt = new Date()) {
let curDate = new Date() // 当前日期
let comparedDate= new Date(typeof dt === 'string'&&dt.includes('-')?dt.replace(/-/g,'/'):dt) // 传入日期
return curDate.getFullYear() === comparedDate.getFullYear() && // 年相等
curDate.getMonth() === comparedDate.getMonth() && // 月相等
curDate.getDate() === comparedDate.getDate() // 日相等
}
时间戳转化日期格式(简约)
/*
* @name: timestampToTime
* @description: 时间戳转化日期格式
* @param:timestamp {Number} 时间戳
* flag {Boolean} 默认值true,时间戳为10位传true,时间戳为13位传flase
* @return: {String} 转换后数字
* @example: timestampToTime(1403058804) => 2014-06-18 10:33:24
*/
export function timestampToTime(timestamp, flag=true) {
//时间戳为10位需*1000,时间戳为13位的话不需乘1000
let date = flag ? new Date(timestamp * 1000) : new Date(timestamp);
Y = date.getFullYear() + '-';
M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
D = date.getDate() + ' ';
h = date.getHours() + ':';
m = date.getMinutes() + ':';
s = date.getSeconds();
return Y+M+D+h+m+s;
}
时间戳转化日期格式(豪华)
/**
* @description: 日期时间格式化函数
* @param { Array } args :形参数组,生效的最多为前两个参数
* 1个参数情况:
* 1.1 参数为格式,则默认格式化当前时间
* 1.2 参数为时间戳或字符串时间,则使用默认格式去格式化化给定的 时间戳或字符串时间
* 2个参数情况:
* 第一个参数表示格式化的日期,可以是时间戳或字符串时间
* 第二个参数表示格式
*/
const format = function (...args) {
try {
// 参数解构
const [a, b] = args
// 默认值
let dt = new Date(), //默认当前时间
ft = 'YYYY-MM-DD HH:mm:ss' // 默认格式
//如果参数只传入了一个的情况,我们认为用户用户传入的是格式,需要格式化的是当前时间
if (args.length == 1) {
if (isNaN(new Date(a).valueOf())) {
ft = a
} else {
dt = new Date(typeof a == 'string' && a.includes('-') ? a.replace(/-/g, '/') : a)
}
} else if (args.length >= 2) {
dt = new Date(typeof a == 'string' && a.includes('-') ? a.replace(/-/g, '/') : a)
ft = b
}
const map = {
Y: String(dt.getFullYear()), //4位数 年份
M: String(dt.getMonth() + 1).padStart(2, 0), // 2位数 月份
D: String(dt.getDate()).padStart(2, 0), // 2位数 日期
H: String(dt.getHours()).padStart(2, 0), // 2位数 时
m: String(dt.getMinutes()).padStart(2, 0), // 2位数 分
s: String(dt.getSeconds()).padStart(2, 0), //2位数 秒
S: String(dt.getMilliseconds()).padStart(3, 0), // 3位数 毫秒
Q: Math.floor((dt.getMonth() + 3) / 3) + '' //季度
}
return ft.replace(/\[([^\]]+)]|y{1,4}|Y{1,4}|M{1,2}|d{1,2}|D{1,2}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|q|t|S{1,3}/g, match => {
// 匹配中的首字符
let k = match[0]
// 匹配到的字符串长度
let len = match.length
switch (k) {
case 'y':
case 'Y':
return match.replace(new RegExp('((' + k + ')+)', 'g'), a => map.Y.substr(4 - a.length))
case 'M':
return len == 1 ? Number(map.M) : map.M
case 'D':
case 'd':
return len == 1 ? Number(map.D) : map.D
case 'H':
case 'h':
return len == 1 ? Number(map.H) : map.H
case 'm':
return len == 1 ? Number(map.m) : map.m
case 's':
return len == 1 ? Number(map.s) : map.s
case 'S':
return match.replace(new RegExp('((' + k + ')+)', 'g'), a => map.S.substr(3 - a.length))
case '[':
return match.replace(/\[|\]/g, '')
case 'q':
return map.Q
default:
return match
}
})
} catch (e) {
return new Date('') // Invalid Date
}
}
当前是今年的第几天
const dayOfYear = date =>
Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
dayOfYear(new Date()); // 272
获取月最后一天是几号
// 将最后一天日期入参数填为0
const Y = new Date().getFullYear();
const M = new Date().getMonth() + 1;
const LastDay = new Date(Y, M, 0).getDate();
// daysInMonth
const daysInMonth = function (month = new Date().getMonth() + 1, dt = new Date()) {
let is = month >= 1 && month <= 12
dt = is ? dt : month
month = is ? month : new Date(month).getMonth() + 1
let date = new Date(typeof dt === 'string' && dt.includes('-') ? dt.replace(/-/g, '/') : dt.toString())
const year = date.getFullYear()
return new Date(year, month, 0).getDate()
}
从Date对象里获取当前时间
此段代码从Date对象里获取当前时间。
const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
getColonTimeFromDate(new Date()); // "08:38:00"
两个日期之间相差多少天
此段代码返回两个日期之间相差多少天
const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
(dateFinal - dateInitial) / (1000 * 3600 * 24);
getDaysDiffBetweenDates(new Date('2019-01-13'), new Date('2019-01-15')); // 2
日期早于和日期晚于
// 接收两个日期类型的参数,判断前者的日期是否晚于后者的日期。
const isAfterDate = (dateA, dateB) => dateA > dateB;
isAfterDate(new Date(2010, 10, 21), new Date(2010, 10, 20)); // true
// 接收两个日期类型的参数,判断前者的日期是否早于后者的日期。
const isBeforeDate = (dateA, dateB) => dateA < dateB;
isBeforeDate(new Date(2010, 10, 20), new Date(2010, 10, 21)); // true
刚刚
、几秒前
、几分钟前
// date为传入时间 例:"2023/5/10 11:32:01" 2023-02-01 09:32:01
// type为返回类型 例:- / 年月日 年
// 默认规则,大于等于一天(24小时)展示'X天前;大于等于30天且小于365天展示'X个月前';
// 大于等于365天且展示'x年前',否则按照传入参数规则展示
// zeroFillFlag参数为是否数字补零,默认补零
// 时间参数date为必写参数
const formatPast = (date, type = "default", zeroFillFlag = true) => {
// 定义countTime变量,用于存储计算后的数据
let countTime;
// 获取当前时间戳
let time = new Date().getTime();
// 转换传入参数为时间戳
let afferentTime = new Date(date).getTime();
// 当前时间戳 - 传入时间戳
time = Number.parseInt(`${time - afferentTime}`);
if (time < 10000) {
// 10秒内
return "刚刚";
} else if (time < 60000) {
// 超过10秒少于1分钟内
countTime = Math.floor(time / 1000);
return `${countTime}秒前`;
} else if (time < 3600000) {
// 超过1分钟少于1小时
countTime = Math.floor(time / 60000);
return `${countTime}分钟前`;
} else if (time < 86400000) {
// 超过1小时少于24小时
countTime = Math.floor(time / 3600000);
return `${countTime}小时前`;
} else if (time >= 86400000 && type == "default") {
// 超过二十四小时(一天)且格式参数为默认"default"
countTime = Math.floor(time / 86400000);
//大于等于365天
if (countTime >= 365) {
return `${Math.floor(countTime / 365)}年前`;
}
//大于等于30天
if (countTime >= 30) {
return `${Math.floor(countTime / 30)}个月前`;
}
return `${countTime}天前`;
} else {
// 一天(24小时)以上且格式不为"default"则按传入格式参数显示不同格式
// 数字补零
let Y = new Date(date).getFullYear();
let M = new Date(date).getMonth() + 1;
let zeroFillM = M > 9 ? M : "0" + M;
let D = new Date(date).getDate();
let zeroFillD = D > 9 ? D : "0" + D;
// 传入格式为"-" "/" "."
if (type == "-" || type == "/" || type == ".") {
return zeroFillFlag
? Y + type + zeroFillM + type + zeroFillD
: Y + type + M + type + D;
}
// 传入格式为"年月日"
if (type == "年月日") {
return zeroFillFlag
? Y + type[0] + zeroFillM + type[1] + zeroFillD + type[2]
: Y + type[0] + M + type[1] + D + type[2];
}
// 传入格式为"月日"
if (type == "月日") {
return zeroFillFlag
? zeroFillM + type[0] + zeroFillD + type[1]
: M + type[0] + D + type[1]
}
// 传入格式为"年"
if (type == "年") {
return Y + type
}
}
};
其他
【JavaScript】常用正则
【JavaScript】常用快查 - 客户端
【JavaScript】常用快查 - 断言