javascript 常用工具类
大约 10 分钟
javascript 常用工具类
数组
判断是否是数组
/**
* @desc 判断是否是数组
* @param {Array}} arr 数组
*/
export const arrJudge = (arr) => {
if (Array.isArray(arr)) {
return true
}
}
数组去重
/**
* @desc 数组去重
* @param {Array} arr 数组
*/
export const arrRemoveRepeat = (arr) => {
return Array.from(new Set(arr))
}
数组对象去重
/**
* @desc 数组对象去重
* @param {Array} arr1 数组对象 [{ id: 1 }, { id: 2 }, { id: 3 }];
* @param {Array} arr2 数组对象 [{ id: 3 }, { id: 4 }, { id: 5 }];
* @retrun {Array} [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 } ]
*/
export const mergeArray = (arr1, arr2) => {
// 克隆
const cloneArr1 = arr1.slice(0)
let v
for (let i = 0; i < arr2.length; i++) {
v = arr2[i]
// 能找到相同 id 属性值的数据则进入判断
// ~按位非 ~~双非
if (~cloneArr1.findIndex((el) => el.id === v.id)) {
continue
}
cloneArr1.push(v)
}
return cloneArr1
}
数组排序
/**
* @desc 数组排序
* @param {Array} arr 数组
* @param {Boolean} ascendFlag 升序,默认为 true
*/
export const arrOrderAscend = (arr, ascendFlag = true) => {
return arr.sort((a, b) => {
return ascendFlag ? a - b : b - a
})
}
数组最大值
/**
* @desc 数组最大值
* @param {Array} arr 数组
*/
export const arrMax = (arr) => {
return Math.max(...arr)
}
数组求和
/**
* @desc 数组求和
* @param {Array} arr 数组
*/
export const arrSum = (arr) => {
return arr.reduce((prev, cur) => {
return prev + cur
}, 0)
}
数组对象求和
/**
* @desc 数组对象求和
* @param {Object} arrObj 数组对象
* @param {String} key 数组对应的 key 值
*/
// eslint-disable-next-line no-unused-vars
export const arrObjSum = (obj, key) => {
// eslint-disable-next-line no-undef
return arrObj.reduce((prev, cur) => prev + cur.key, 0)
}
数组合并,目前合并一维
/**
* @desc 数组合并,目前合并一维
* @param {Array} arrOne 数组
* @param {Array} arrTwo 数组
*/
export const arrConcat = (arrOne, arrTwo) => {
return [...arrOne, ...arrTwo]
}
数组是否包含某值
/**
* @desc 数组是否包含某值
* @param {Array} arr 数组
* @param {} value 值,目前只支持 String,Number,Boolean
*/
export const arrIncludeValue = (arr, value) => {
return arr.includes(value)
}
数组并集,只支持一维数组
/**
* @desc 数组并集,只支持一维数组
* @param {Array} arrOne
* @param {Array} arrTwo
*/
export const arrAndSet = (arrOne, arrTwo) => {
return arrOne.concat(arrTwo.filter((v) => !arrOne.includes(v)))
}
数组交集,只支持一维数组
/**
* @desc 数组交集,只支持一维数组
* @param {Array} arrOne
* @param {Array} arrTwo
*/
export const arrIntersection = (arrOne, arrTwo) => {
return arrOne.filter((v) => arrTwo.includes(v))
}
数组差集,只支持一维数组
/**
* @desc 数组差集,只支持一维数组
* @param {Array} arrOne
* @param {Array} arrTwo
* eg: [1, 2, 3] [2, 4, 5] 差集为[1,3,4,5]
*/
export const arrDifference = (arrOne, arrTwo) => {
return arrOne
.concat(arrTwo)
.filter((v) => !arrOne.includes(v) || !arrTwo.includes(v))
}
两个数组合并成一个对象数组,考虑到复杂度,所以目前支持两个一维数组
/**
* @desc 两个数组合并成一个对象数组,考虑到复杂度,所以目前支持两个一维数组
* @param {Array} arrOne
* @param {Array} arrTwo
* @param {oneKey} oneKey 选填,如果两个都未传,直接以 arrOne 的值作为 key,arrTwo 作为 value
* @param {twoKey} twoKey
*/
export const arrTwoToArrObj = (arrOne, arrTwo, oneKey, twoKey) => {
if (!oneKey && !twoKey) {
return arrOne.map((oneKey, i) => ({ [oneKey]: arrTwo[i] }))
} else {
return arrOne.map((oneKey, i) => ({ oneKey, twoKey: arrTwo[i] }))
}
}
将对象转化为对象数组
/**
* @desc 将对象转化为对象数组
* @param {Object} objData
*/
export const objToArr = (objData) => {
var arr = []
for (let i in objData) {
let o = {}
// eslint-disable-next-line no-undef
o[i] = obj[i] //即添加了key值也赋了value值 o[i] 相当于o.name 此时i为变量
arr.push(o)
}
return arr
}
多数组相加
/**
* @desc 多数组相加
* @param {arr} arr 二维数组
* [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 4, 5, 6 ] ]
*/
export const arrTotalArray = (arr) => {
let result = []
for (let i = 0; i < arr.length; i++) {
arr[i].forEach((value, index) => {
if (result[index] == null || result[index] == '') {
result[index] = 0
}
result[index] += parseInt(value)
})
}
return result //[ 9, 12, 15 ]
}
优化高频率执行代码
节流
/**
* @desc 节流
* @param {*} func 执行函数
* @param {*} delay 节流时间,毫秒
*/
export const throttle = function (func, delay) {
let timer = null
return function () {
if (!timer) {
timer = setTimeout(() => {
func.apply(this, arguments)
// 或者直接 func()
timer = null
}, delay)
}
}
}
防抖
/**
* @desc 防抖
* @param {*} fn 执行函数
* @param {*} wait 防抖时间,毫秒
*/
export const debounce = function (fn, wait) {
let timeout = null
return function () {
if (timeout !== null) clearTimeout(timeout) // 如果多次触发将上次记录延迟清除掉
timeout = setTimeout(() => {
fn.apply(this, arguments)
// 或者直接 fn()
timeout = null
}, wait)
}
}
URL
获取 url 后面通过?传参的参数
/**
* @desc 获取 url 后面通过?传参的参数
* @param {String} name
*/
export function getQueryString(name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
const url = window.location.href
const search = url.substring(url.lastIndexOf('?') + 1)
const r = search.match(reg)
if (r != null) return unescape(r[2])
return null
}
url 参数转对象
/**
* @desc url参数转对象
* @param {String} url default: window.location.href
* @return {Object}
*/
export function parseQueryString(url) {
url = !url ? window.location.href : url
if (url.indexOf('?') === -1) {
return {}
}
var search =
url[0] === '?' ? url.substr(1) : url.substring(url.lastIndexOf('?') + 1)
if (search === '') {
return {}
}
search = search.split('&')
var query = {}
for (var i = 0; i < search.length; i++) {
var pair = search[i].split('=')
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '')
}
return query
}
正则
判断是否是数字
/**
* @desc 判断是否是数字
* @param {Number} data
*/
export const checkNum = (data) => {
const reg = /^\d{1,}$/g
if (reg.test(data)) return true
}
判断是否是字母
/**
* @desc 判断是否是字母
* @param {Number} data
*/
export const checkLetter = (data) => {
const reg = /^[a-zA-Z]+$/g
if (reg.test(data)) return true
}
判断是否全部是小写字母
/**
* @desc 判断是否全部是小写字母
* @param {Number} data
*/
export const checkLowercaseLetter = (data) => {
const reg = /^[a-z]+$/g
if (reg.test(data)) return true
}
判断是否是大写字母
/**
* @desc 判断是否是大写字母
* @param {Number} data
*/
export const checkCapitalLetter = (data) => {
const reg = /^[A-Z]+$/g
if (reg.test(data)) return true
}
判断是否是字母或数字
/**
* @desc 判断是否是字母或数字
* @param {Number || String} data 字符或数字
*/
export const checkNumOrLetter = (data) => {
const reg = /^[0-9a-zA-Z]*$/g
if (reg.test(data)) return true
}
判断是否是中文
/**
* @desc 判断是否是中文
* @param {String} data 中文
*/
export const checkChinese = (data) => {
const reg = /^[\u4E00-\u9FA5]+$/g
if (reg.test(data)) return true
}
判断是否是中文,数字或字母
/**
* @desc 判断是否是中文,数字或字母
* @param {String} data 中文,数字或字母
*/
export const checkChineseNumberLettter = (data) => {
const reg = /^[a-zA-Z0-9\u4e00-\u9fa5]+$/g
if (reg.test(data)) return true
}
判断是否是邮箱地址
/**
* @desc 判断是否是邮箱地址
* @param {String} data
*/
export const checkEmail = (data) => {
const reg =
/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/g
if (reg.test(data)) return true
}
判断是否是手机号
/**
* @desc 判断是否是手机号,只要是13,14,15,16,17,18,19开头即可
* @param {String} data
*/
export const checkTelphone = (data) => {
const reg = /^((\+|00)86)?1[3-9]\d{9}$/g
if (reg.test(data)) return true
}
判断是否是正确的网址
/**
* @desc 判断是否是正确的网址
* @param {String} url 网址
*/
export const checkUrl = (url) => {
const a = document.createElement('a')
a.href = url
return (
[
/^(http|https):$/.test(a.protocol),
a.host,
a.pathname !== url,
a.pathname !== `/${url}`
].find((x) => !x) === undefined
)
}
判断是否为 16 进制颜色
/**
* @desc 判断是否为16进制颜色,rgb 或 rgba
* @param {String} str
* @return {Boolean}
*/
export const isColor = (str) => {
return /^(#([0-9a-fA-F]{3}){1,2}|[rR][gG][Bb](\((\s*(2[0-4]\d|25[0-5]|[01]?\d{1,2})\s*,){2}\s*(2[0-4]\d|25[0-5]|[01]?\d{1,2})\s*\)|[Aa]\((\s*(2[0-4]\d|25[0-5]|[01]?\d{1,2})\s*,){3}\s*([01]|0\.\d+)\s*\)))$/.test(
str
)
}
判断是否为身份证号
/**
* @desc 判断是否为身份证号
* @param {String|Number} str
* @return {Boolean}
*/
export const isIdCard = (str) => {
return /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/.test(
str
)
}
客户端环境检测
判断是浏览器内核
/**
* @desc 判断是浏览器内核
*/
export const checkBrowser = () => {
const u = navigator.userAgent
const obj = {
trident: u.indexOf('Trident') > -1, //IE内核
presto: u.indexOf('Presto') > -1, //opera内核
webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1 //火狐内核
}
return Object.keys(obj)[Object.values(obj).indexOf(true)]
}
判断是终端类型,值有 ios,android,iPad
/**
* @desc 判断是终端类型,值有ios,android,iPad
*/
export const checkIosAndroidIpad = () => {
const u = navigator.userAgent
const obj = {
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器
iPad: u.indexOf('iPad') > -1 //是否iPad
}
return Object.keys(obj)[Object.values(obj).indexOf(true)]
}
判断是否是微信,qq 或 uc
/**
* @desc 判断是否是微信,qq 或 uc
*/
export const checkWeixinQqUc = () => {
const u = navigator.userAgent
const obj = {
weixin: u.indexOf('MicroMessenger') > -1, //是否微信
qq: u.match(/QQ/i) == 'qq' && !u.indexOf('MQQBrowser') > -1, //是否QQ
uc: u.indexOf('UCBrowser') > -1
}
return Object.keys(obj)[Object.values(obj).indexOf(true)]
}
检查是否是 IphoneX
/**
* @desc 检查是否是 IphoneX
*/
export const checkIsIphoneX = () => {
const u = navigator.userAgent
const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
if (isIOS && screen.height >= 812) {
return true
}
}
判断浏*览器是否支持 webP 格式图片
/**
* @desc 判断浏*览器是否支持webP格式图片
* @return {Boolean}
*/
export const isSupportWebP = () => {
return (
!![].map &&
document
.createElement('canvas')
.toDataURL('image/webp')
.indexOf('data:image/webp') == 0
)
}
时间/日期
获取年份
/**
* @desc 获取年份
*/
export const getYear = () => {
return new Date().getFullYear()
}
获取当前月份
/**
* @desc 获取当前月份
* @param {Boolean} fillFlag 布尔值,是否补 0,默认为 true
*/
export const getMonth = (fillFlag = true) => {
const mon = new Date().getMonth() + 1
const monRe = mon
if (fillFlag) mon < 10 ? `0${mon}` : mon
return monRe
}
获取日
/**
* @desc 获取日
* @param {Boolean} fillFlag 布尔值,是否补 0
*/
export const getDay = (fillFlag = true) => {
const day = new Date().getDate()
const dayRe = day
if (fillFlag) day < 10 ? `0${day}` : day
return dayRe
}
获取星期几
/**
* @desc 获取星期几
*/
export const getWhatDay = () => {
return new Date().getDay() ? new Date().getDay() : 7
}
获取当前月天数
/**
* @desc 获取当前月天数
* @param {String} year 年份
* @param {String} month 月份
*/
export const getMonthNum = (year, month) => {
var d = new Date(year, month, 0)
return d.getDate()
}
获取当前时间 yyyy-mm-dd,hh:mm:ss
/**
* @desc 获取当前时间 yyyy-mm-dd,hh:mm:ss
*/
export const getYyMmDdHhMmSs = () => {
const date = new Date()
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hours = date.getHours()
const minu = date.getMinutes()
const second = date.getSeconds()
const arr = [month, day, hours, minu, second]
arr.forEach((item) => {
item < 10 ? '0' + item : item
})
return (
year +
'-' +
arr[0] +
'-' +
arr[1] +
' ' +
arr[2] +
':' +
arr[3] +
':' +
arr[4]
)
}
时间戳转化为年月日
function getzf(time) {
return +time < 10 ? `0${time}` : time
}
/**
* @desc 时间戳转化为年月日
* @param times 时间戳
* @param ymd 格式类型(yyyy-mm-dd,yyyy/mm/dd)
* @param hms 可选,格式类型(hh,hh:mm,hh:mm:ss)
* @returns {年月日}
*/
export const timesToYyMmDd = (times, ymd, hms) => {
const oDate = new Date(times)
const oYear = oDate.getFullYear()
const oMonth = oDate.getMonth() + 1
const oDay = oDate.getDate()
const oHour = oDate.getHours()
const oMin = oDate.getMinutes()
const oSec = oDate.getSeconds()
let oTime // 最后拼接时间
// 年月日格式
switch (ymd) {
case 'yyyy-mm-dd':
oTime = oYear + '-' + getzf(oMonth) + '-' + getzf(oDay)
break
case 'yyyy/mm/dd':
oTime = oYear + '/' + getzf(oMonth) + '/' + getzf(oDay)
break
}
// 时分秒格式
switch (hms) {
case 'hh':
oTime = ' ' + oTime + getzf(oHour)
break
case 'hh:mm':
oTime = oTime + getzf(oHour) + ':' + getzf(oMin)
break
case 'hh:mm:ss':
oTime = oTime + getzf(oHour) + ':' + getzf(oMin) + ':' + getzf(oSec)
break
}
return oTime
}
将年月日转化成时间戳
/**
* @desc 将年月日转化成时间戳
* @param {String} time yyyy/mm/dd 或yyyy-mm-dd 或yyyy-mm-dd hh:mm 或yyyy-mm-dd hh:mm:ss
*/
export const YyMmDdToTimes = (time) => {
return new Date(time.replace(/-/g, '/')).getTime()
}
比较时间 1 小于时间 2
/**
* @desc 比较时间 1 小于时间 2
* @param {String} timeOne 时间 1
* @param {String} timeTwo 时间 2
*/
export const compareTimeOneLessTwo = (timeOne, timeTwo) => {
// 判断 timeOne 和 timeTwo 是否
return (
new Date(timeOne.replace(/-/g, '/')).getTime() <
new Date(timeTwo.replace(/-/g, '/')).getTime()
)
}
时间戳转化为年月日
/**
* @desc 时间戳转化为年月日
* @param {Date} startTime
* @return {String}
*/
export const formatPassTime = (startTime) => {
const currentTime = Date.parse(new Date()),
time = currentTime - startTime,
day = parseInt(time / (1000 * 60 * 60 * 24)),
hour = parseInt(time / (1000 * 60 * 60)),
min = parseInt(time / (1000 * 60)),
month = parseInt(day / 30),
year = parseInt(month / 12)
if (year) return year + '年前'
if (month) return month + '个月前'
if (day) return day + '天前'
if (hour) return hour + '小时前'
if (min) return min + '分钟前'
else return '刚刚'
}
格式化现在距${endTime}的剩余时间
/**
* @desc 格式化现在距${endTime}的剩余时间
* @param {Date} endTime
* @return {String}
*/
export const formatRemainTime = (endTime) => {
var startDate = new Date() //开始时间
var endDate = new Date(endTime) //结束时间
var t = endDate.getTime() - startDate.getTime() //时间差
var d = 0,
h = 0,
m = 0,
s = 0
if (t >= 0) {
d = Math.floor(t / 1000 / 3600 / 24)
h = Math.floor((t / 1000 / 60 / 60) % 24)
m = Math.floor((t / 1000 / 60) % 60)
s = Math.floor((t / 1000) % 60)
}
return d + '天 ' + h + '小时 ' + m + '分钟 ' + s + '秒'
}
判断是否为同一天
/**
* @desc 判断是否为同一天
* @param {Date} date1
* @param {Date} date2 可选/默认值:当天
* @return {Boolean}
*/
export const isSameDay = (date1, date2) => {
if (!date2) {
date2 = new Date()
}
var date1_year = date1.getFullYear(),
date1_month = date1.getMonth() + 1,
date1_date = date1.getDate()
var date2_year = date2.getFullYear(),
date2_month = date2.getMonth() + 1,
date2_date = date2.getDate()
return (
date1_date === date2_date &&
date1_month === date2_month &&
date1_year === date2_year
)
}
计算${startTime - endTime}的剩余时间
/**
* @desc 计算${startTime - endTime}的剩余时间 ,startTime大于endTime时,均返回0
* @param { Date | String } startTime
* @param { Date | String } endTime
* @returns { Object } { d, h, m, s } 天 时 分 秒
*/
export const timeLeft = (startTime, endTime) => {
if (!startTime || !endTime) {
return
}
var startDate, endDate
if (startTime instanceof Date) {
startDate = startTime
} else {
startDate = new Date(startTime.replace(/-/g, '/')) //开始时间
}
if (endTime instanceof Date) {
endDate = endTime
} else {
endDate = new Date(endTime.replace(/-/g, '/')) //结束时间
}
var t = endDate.getTime() - startDate.getTime()
var d = 0,
h = 0,
m = 0,
s = 0
if (t >= 0) {
d = Math.floor(t / 1000 / 3600 / 24)
h = Math.floor((t / 1000 / 60 / 60) % 24)
m = Math.floor((t / 1000 / 60) % 60)
s = Math.floor((t / 1000) % 60)
}
return { d, h, m, s }
}