今日主要分享一些平时常用的utils工具函数,有需要的可以参考一下
时间数字转换
function formatNumber(n) {
n = (~~n).toString()
return n[1] ? n : '0' + n
}
这里的 ~ 是js的一个按位取反运算,一个~代表取反一次,2个就是取反2次,那不就是没变吗?其实这里是由于运算的操作值要求是整数,所以这里就可以用来去掉小数部分转换数字了。
判断对象是否为空
function isEmpty(obj) {
let tostring = Object.prototype.toString
if (obj == null) return true
if (
tostring.call(obj) == '[object Array]' ||
tostring.call(obj) == '[object String]'
) {
return obj.length === 0
}
if (tostring.call(obj) == '[object Object]') {
for (let name in obj) {
return false
}
}
return true
}
这里一般用来处理接口返回得数据,针对null、空字符串、空数组,空对象判空处理。
防抖
function debounce(fn, wait) {
let timerId=null
wait = wait || 0
function debounced() {
let that = this,
args = arguments
if (timerId) {
clearTimeout(timerId)
timerId = null
}
timerId = setTimeout(() => {
fn.apply(that, args)
}, wait)
}
return debounced
}
节流
function throttle(fn, gapTime) {
let _lastTime = null
gapTime = gapTime || 0
return function () {
let that = this,
args = arguments,
_nowTime = + new Date()
if (_nowTime - _lastTime > gapTime || !_lastTime) {
fn.apply(that, args)
_lastTime = _nowTime
}
}
}
对象属性转url参数
function formatOptions(options) {
var urlOptions = ''
for (var i in options) {
urlOptions += i + '=' + options[i] + '&'
}
urlOptions = urlOptions.slice(0, urlOptions.length - 1)
return urlOptions
}
例:{a:1,b:2,c:3} 返回:a=1&b=2&c=3
是否是数字
function isRealNum(num) {
if (num === '' || num === null) {
return false;
}
if (typeof num === 'number' && !isNaN(num)) {
return true;
}
return false;
}
这里为什么不只用isNaN是因为isNaN的缺点就在于 null、空格以及空串会被按照0来处理
比较数据是否一致
function equals(a, b) {
if (a === b) return true;
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
if (a.prototype !== b.prototype) return false;
let keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) return false;
return keys.every(k => equals(a[k], b[k]));
}
加减法运算
/**
* 计算
* @param {*} l 操作数1
* @param {*} r 操作数2
* @param {*} sign 操作符
* @param {*} f 精度
*/
function operate(l, r, sign, f) {
switch (sign) {
case '+': return (l + r) / f
case '-': return (l - r) / f
case '*': return (l * r) / (f * f)
case '/': return (l / r)
}
}
/**
* 解决小数精度问题
* @param {*} l 操作数1
* @param {*} r 操作数2
* @param {*} sign 操作符
* fixedFloat(0.3, 0.2, '-')
*/
function fixedFloat(l, r, sign) {
const arrL: any = split(l)
const arrR: any = split(r)
let fLen = Math.max(arrL[1], arrR[1])
if (fLen === 0) {
return operate(Number(l), Number(r), sign, 1)
}
const f = Math.pow(10, fLen)
if (arrL[1] !== arrR[1]) {
if (arrL[1] > arrR[1]) {
arrR[0] += padding0(arrL[1] - arrR[1])
} else {
arrL[0] += padding0(arrR[1] - arrL[1])
}
}
return operate(Number(arrL[0]), Number(arrR[0]), sign, f)
}
是否身份证
const isIDCard = (idCard) => {
let num: any = idCard.toLowerCase().match(/\w/g)
if (idCard.match(/^\d{17}[\dx]$/i)) {
let sum = 0
let times = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
for (let i = 0; i < 17; i++) {
sum += parseInt(num[i], 10) * times[i]
}
if ('10x98765432'.charAt(sum % 11) !== num[17]) {
return false
}
return !!idCard.replace(/^\d{6}(\d{4})(\d{2})(\d{2}).+$/, '$1-$2-$3')
}
return false
}
是否是当天
const isToday = (value) => {
if (isString(value) || isNumber(value)) {
value = newDate(value)
}
let now = new Date()
let today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
let start = new Date(value.getFullYear(), value.getMonth(), value.getDate())
return today.getTime() === start.getTime()
}
获取请求参数
/**
* 获取请求参数方法
* @param 参数
* paramKey : 参数名称
* part : 非必传, 空:默认所有参数中取最后一个,search:从search中获取,hash:从hash中获取
* caseState : 是否区分大小写,默认不区分
*/
const getQueryParam = (paramKey, part = '', caseState = false) => {
let queryUrl = window.location.href
if (part) {
if (part === 'search') queryUrl = window.location.search
if (part === 'hash') queryUrl = window.location.hash
}
const paramsArr = queryUrl.split('?')
let url = ''
if (paramsArr.length > 1) {
url = paramsArr.reduce((pre: any, cur: any, index: Number) => {
if (index > 0) {
pre += '&' + cur.replace(/(\/|#)/g, '')
}
return pre
}, '')
} else {
url = window.location.href.split('?')[1] || ''
}
let params: Param = {}
// 默认转换为小写
if (!caseState) {
paramKey = paramKey.toLocaleLowerCase()
}
let urlArr = url.replace(/(\/)#[^&]*/, '').split('&')
for (let i = 0; i < urlArr.length; i++) {
let num = urlArr[i].indexOf('=')
if (num > 0) {
let key = decodeURIComponent(urlArr[i].substring(0, num))
if (!caseState) {
key = key.toLocaleLowerCase()
}
let val = urlArr[i].substring(num + 1) || ''
try {
val = decodeURIComponent(val)
} catch (ex) { }
params[key] = val
}
}
return params[paramKey]
}
创建随机数
const randomString = (len = 32) => {
const t = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnoprstuvwxyz1234567890'
let a = t.length
let str = ''
for (let i = 0; i < len; i++) {
str += t.charAt(Math.floor(Math.random() * a))
}
return str
}
获取hash参数
const getHashParam = (params, caseSen = false) => {
let hash = location.hash
let hashQMarkPos = hash.indexOf('?') // 以问号为界
let hashQuery = hash.substring(hashQMarkPos + 1) // vue在hash中的查询参数
let hashStrArr = hashQuery.split('&')
let hashNewArr: Param = {}
hashStrArr.forEach((item) => {
let keyVal = item.split('=')
let k = keyVal[0]
let v = keyVal[1]
hashNewArr[k] = v
})
return hashNewArr[params]
}
加载js
let scriptCaches: string[] = []
const loadJS = (src) => {
return new Promise(resolve => {
if (scriptCaches.includes(src)) resolve(true)
// var oHead = document.getElementsByTagName('HEAD').item(0);
const scriptEL = document.createElement("script");
scriptEL.type = "text/javascript"
scriptEL.src = src
document.body.appendChild(scriptEL)
scriptEL.onload = function () {
console.log('loaded')
resolve(true)
}
scriptEL.onerror = function () {
resolve(false)
}
})
}
深拷贝
const deepCopy = (obj, deep = {}) => {
for (let i in obj) {
if (Object.prototype.toString.call(obj[i]) === '[object Object]') {
deep[i] = deepCopy(obj[i])
} else if (Array.isArray(obj[i])) {
deep[i] = deepCopy(obj[i], [])
} else {
deep[i] = obj[i]
}
}
return deep
}