js常用工具函数大全

js工具函数

 

判断数据类型

Object.prototype.toString.call(5)               // "[object Number]"
Object.prototype.toString.call('str')           // "[object String]"
Object.prototype.toString.call(true)            // "[object Boolean]"
Object.prototype.toString.call(undefined)       // "[object Undefined]"
Object.prototype.toString.call(null)            // "[object Null]"
Object.prototype.toString.call(function () { }) // "[object Function]"
Object.prototype.toString.call([])              // "[object Array]"
Object.prototype.toString.call({})              // "[object Object]"

function checkDataType (value) {
  const typeObj = Object.prototype.toString.call(value)
  return typeObj.slice(8, -1)
}

 

完整深拷贝

 function deepCopy1(obj, hash = new WeakMap()) {
  // 日期对象直接返回一个新的日期对象
  if (obj.constructor === Date) return new Date(obj)
  // 正则对象直接返回一个新的正则对象
  if (obj.constructor === RegExp) return new RegExp(obj)
  // 如果循环引用了就用WeakMap解决
  if (hash.has(obj)) return hash.get(obj)

  // 遍历传图参数所有键的特性
  let allDesc = Object.getOwnPropertyDescriptor(obj)
  // 继承原型链
  let copyObj = Object.create(Object.getPrototypeOf(obj), allDesc)
  hash.set(obj, copyObj)
  for (let key of Reflect.ownKeys(obj)) {
    copyObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepCopy(obj[key], hash) : obj[key]
  }
  function isComplexDataType(obj) {
    return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
  }
  return copyObj
}

 

格式化时间

 /*
 * 格式化时间
 * 传入参数 date 被格式的时间,例如:var date = new Date();
 * 传入参数 fmt 输出的时间格式,例如:yyyy-MM-dd
 * 返回 格式化的时间
 */
function formatDate(date, fmt) {
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  let o = {
    'M+': date.getMonth() + 1,
    'd+': date.getDate(),
    'h+': date.getHours(),
    'm+': date.getMinutes(),
    's+': date.getSeconds()
  }
  for (let k in o) {
    if (new RegExp(`(${k})`).test(fmt)) {
      let str = o[k] + ''
      fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : padLeftZero(str))
    }
  }
  function padLeftZero(str) {
    return ("00" + str).substr(str.length);
  }
  return fmt
}

 

格式化数值


/**
 * 数值格式化
 * @param number - 数值
 * @param places - 保留小数位
 * @param symbol - 前缀
 * @param thousand - 分隔符
 * @param decimal - 小数位符号
 * @param isFormat
 * @return {string}
 */
export function formatNumber (
  number = 0,
  places = 0,
  symbol = '',
  thousand = ',',
  decimal = '.',
  isFormat = true
) {
  places = !isNaN((places = Math.abs(places))) ? places : 2
  let negative = number < 0 ? '-' : ''
  let i = parseInt((number = Math.abs(+number || 0).toFixed(places)), 10) + ''
  let j = i.length > 3 ? i.length % 3 : 0
  let num =
    (j ? i.substr(0, j) + thousand : '') +
    i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand) +
    (places
      ? decimal +
      Math.abs(number - i)
        .toFixed(places)
        .slice(2)
      : '')

  if (isFormat) {
    num = num.match(/[\d,]+(?:\.\d*[1-9]+)?/)[0]
  }

  return symbol + negative + num
}

 

本地存储方法封装

class Storage {
  constructor(o) {
    this.o = o;
  }

  getItem(key) {
    return JSON.parse(this.o.getItem(key)) || "";
  }

  setItem(key, value) {
    this.o.setItem(key, JSON.stringify(value));
  }

  removeItem(key) {
    this.o.removeItem(key);
  }

  clear() {
    this.o.clear();
  }
}

const { localStorage, sessionStorage } = window;

// lStorage是对localStorage的封装
export const lStorage = new Storage(localStorage);
// sStorage是对sessionStorage的封装
export const sStorage = new Storage(sessionStorage);

export default {
  STORAGE_KEYS,
  lStorage,
  sStorage
};

 

window.resize事件封装

const resizeList = {}
const prefix = 'vue-resize-'
export const $resize = {
  /**
   * 注册监听
   * @param name { String } - 自定义事件别名
   * @param callback { Function } - 回调函数
   * @param duration=100 可自定义间隔执行时间
   */
  add: (name, callback, duration = 100) => {
    const _name = prefix + name
    let timer = ''

    if (resizeList[_name]) {
      console.error(name + ' already exists')
    } else {
      resizeList[_name] = () => {
        if (timer) clearTimeout(timer)
        timer = setTimeout(callback, duration)
      }

      window.addEventListener('resize', resizeList[_name])
    }
  },

  /**
   * 移除监听
   * @param name 自定义事件别名
   */
  remove: name => {
    const _name = prefix + name
    const resize = resizeList[_name]

    if (resize) {
      window.removeEventListener('resize', resize)
      delete resizeList[_name]
    }
  }
}

 

轮播 + 鼠标滚动

/**
 * 轮播 + 鼠标滚动
 * @param {*} el 需要滚动的元素
 * @param {*} distance 要滚动的距离
 * @param {*} duration 单次滚动周期,默认值2000ms
 * 注意:当滚动到底部时,可以根据条件触发`el.scrollTop = 0`复位后再次轮播
 */
export const handleScrollTop = (el, distance, duration = 2000) => {
  const cosParameter = distance / 2
  const cacheScrollTop = el.scrollTop
  const requestAnimationFrame = window.requestAnimationFrame
  let count = 0
  let oldTimestamp = performance.now()
  const step = newTimestamp => {
    count += Math.PI / (duration / (newTimestamp - oldTimestamp))
    if (count >= Math.PI) return
    el.scrollTop = cacheScrollTop + Math.round(cosParameter - cosParameter * Math.cos(count))
    oldTimestamp = newTimestamp
    requestAnimationFrame(step)
  }
  requestAnimationFrame(step)
}

 

获取url附带的参数以及对应的值

 /**
 * @desc 获取url附带的参数以及对应的值
 * @return {Object} obj 返回包含URL参数信息的对象
 */
function getRequest() {
  var obj = {}
  const { href } = window.location
  const i = href.indexOf('?')
  const str = href.substring(i + 1)
  const arr = str.split('&')
  for (var item of arr) {
    let key = item.split('=')[0]
    obj[key] = item.split('=')[1]
  }
  return obj
}

 

自定义的延时器,复写setTimeout方法


/**
 * 自定义的延时器,复写setTimeout方法,优先使用requestAnimationFrame
 */
export const timeDelayFn = (fn, timeout) => {
  let requestAnimationFrame = window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame
  if (requestAnimationFrame) {
    // let s = new Date().getTime()
    const tmpFn = (start, timeout) => {
      if (new Date().getTime() - start < timeout) {
        requestAnimationFrame(() => {
          tmpFn(start, timeout)
        })
      }
    }
  } else {
    window.setTimeout(fn, timeout)
  }
}

 

计算方法封装

 const Calc = {
	/** 加法
	 * @param arg1 { number | string }
	 * @param arg2 { number | string }
	 * @Returns { Number }:两数相加的结果
	 */
  Add: function (arg1, arg2) {
    arg1 = arg1.toString()
    arg2 = arg2.toString()
    let arg1Arr = arg1.split('.')
    let arg2Arr = arg2.split('.')
    let d1 = arg1Arr.length === 2 ? arg1Arr[1] : ''
    let d2 = arg2Arr.length === 2 ? arg2Arr[1] : ''
    let maxLen = Math.max(d1.length, d2.length)
    let m = Math.pow(10, maxLen)
    let result = Number(((arg1 * m + arg2 * m) / m).toFixed(maxLen))
    let d = arguments[2]
    return typeof d === 'number' ? Number(result.toFixed(d)) : result
  },
	/** 减法
	 * @param arg1 { number | string }
	 * @param arg2 { number | string }
	 * @Returns {number}: 两数相减的结果
	 */
  Sub: function (arg1, arg2) {
    return this.Add(arg1, -Number(arg2), arguments[2])
  },
	/** 乘法
	 * @param arg1 { number | string }
	 * @param arg2 { number | string }
	 * @Returns {number}: 两数相乘的结果
	 */
  Mul: function (arg1, arg2) {
    let r1 = arg1.toString()
    let r2 = arg2.toString()
    let m
    let resultVal
    let d = arguments[2]
    m =
      (r1.split('.')[1] ? r1.split('.')[1].length : 0) +
      (r2.split('.')[1] ? r2.split('.')[1].length : 0)
    resultVal = (Number(r1.replace('.', '')) * Number(r2.replace('.', ''))) / Math.pow(10, m)
    return typeof d !== 'number' ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)))
  },
	/** 除法
	 * @param arg1  { number | string }
	 * @param arg2  { number | string }
	 * @Returns {number}: arg1除于arg2的结果
	 */
  Divs: function (arg1, arg2) {
    let r1 = arg1.toString()
    let r2 = arg2.toString()
    let m
    let resultVal
    let d = arguments[2]
    m =
      (r2.split('.')[1] ? r2.split('.')[1].length : 0) -
      (r1.split('.')[1] ? r1.split('.')[1].length : 0)
    resultVal = (Number(r1.replace('.', '')) / Number(r2.replace('.', ''))) * Math.pow(10, m)
    return typeof d !== 'number' ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)))
  }
}

 

H5设定网页标题

 /**
 * @desc H5设定网页标题
 * @param {String} title 标题
 */
function setTitle(title) {
  document.title = title
  // 利用iframe的onload事件刷新页面
  const iframe = document.createElement('iframe')
  iframe.style.visibility = 'hidden'
  iframe.style.width = '1px'
  iframe.style.height = '1px'
  iframe.onload = () => {
    setTimeout(() => {
      document.body.removeChild(iframe)
    }, 0)
  }
  document.body.appendChild(iframe)
}

 

下载文件

/**
 * @desc 下载文件
 * @param {String} data 二进制流文件
 * @param {String} fileName 文件名
 * @param {boolean} transformBlob 是否是Blob,默认不传无需转换
 */
export function download(data, fileName, transformBlob) {
  const blob = !transformBlob ? data : dataURLtoBlob(data);

  const blobUrl = window.URL.createObjectURL(blob);

  // desc:兼容IE浏览器blob文件下载
  if (navigator.msSaveOrOpenBlob) {
    navigator.msSaveOrOpenBlob(blob, fileName);
  } else {
    const a = document.createElement("a");
    a.style.display = "none";
    a.href = blobUrl;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();

    document.body.removeChild(a);
    window.URL.revokeObjectURL(blobUrl);
  }
}

 

base64转blob

/**
 * @desc base64转blob
 * @param {String} dataurl base64
 * @return {Blob} blob
 */
export function dataURLtoBlob(data) {
  const dataAtob = atob(data);
  let dataLength = dataAtob.length;
  const u8arr = new Uint8Array(dataLength);
  while (dataLength--) {
    u8arr[dataLength] = dataAtob.charCodeAt(dataLength);
  }
  return new Blob([u8arr]);
}

 

posted @ 2022-09-06 11:25  丿流水  阅读(213)  评论(0)    收藏  举报