阅读 629

35个前端硬核工具函数,你都get了吗?

小编精心的整理了一些前端日常开发中常用的工具函数,强烈建议收藏,大大提高你的开发效率。

工具函数篇

表单序列化

export const serialize = data => {
  let list = []
  Object.keys(data).forEach(ele => {
    list.push(`${ele}=${data[ele]}`)
  })
  return list.join('&')
}
复制代码

获取对象的类型

export const getObjType = obj => {
  var toString = Object.prototype.toString
  var map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  }
  if (obj instanceof Element) {
    return 'element'
  }
  return map[toString.call(obj)]
}
复制代码

对象深拷贝

export const deepClone = data => {
  var type = getObjType(data)
  var obj
  if (type === 'array') {
    obj = []
  } else if (type === 'object') {
    obj = {}
  } else {
    // 不再具有下一层次
    return data
  }
  if (type === 'array') {
    for (var i = 0, len = data.length; i < len; i++) {
      obj.push(deepClone(data[i]))
    }
  } else if (type === 'object') {
    for (var key in data) {
      obj[key] = deepClone(data[key])
    }
  }
  return obj
}
复制代码

判断路由是否相等

export const diff = (obj1, obj2) => {
  delete obj1.close
  var o1 = obj1 instanceof Object
  var o2 = obj2 instanceof Object
  if (!o1 || !o2) { /*  判断不是对象  */
    return obj1 === obj2
  }

  if (Object.keys(obj1).length !== Object.keys(obj2).length) {
    return false
    // Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,例如:数组返回下标:let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2;
  }

  for (var attr in obj1) {
    var t1 = obj1[attr] instanceof Object
    var t2 = obj2[attr] instanceof Object
    if (t1 && t2) {
      return diff(obj1[attr], obj2[attr])
    } else if (obj1[attr] !== obj2[attr]) {
      return false
    }
  }
  return true
}
复制代码

递归寻找子类的父类

export const findParent = (menu, id) => {
  for (let i = 0; i < menu.length; i++) {
    if (menu[i].children.length != 0) {
      for (let j = 0; j < menu[i].children.length; j++) {
        if (menu[i].children[j].id == id) {
          return menu[i]
        } else {
          if (menu[i].children[j].children.length != 0) {
            return findParent(menu[i].children[j].children, id)
          }
        }
      }
    }
  }
}
复制代码

动态插入css

export const loadStyle = url => {
  const link = document.createElement('link')
  link.type = 'text/css'
  link.rel = 'stylesheet'
  link.href = url
  const head = document.getElementsByTagName('head')[0]
  head.appendChild(link)
}
复制代码

根据字典的value查找对应的index

export const findArray = (dic, value) => {
  for (let i = 0; i < dic.length; i++) {
    if (dic[i].value == value) {
      return i
    }
  }
  return -1
}
复制代码

根据字典的value显示label

export const findByvalue = (dic, value) => {
  let result = ''
  if (validatenull(dic)) return value
  if (typeof (value) === 'string' || typeof (value) === 'number' || typeof (value) === 'boolean') {
    let index = 0
    index = findArray(dic, value)
    if (index != -1) {
      result = dic[index].label
    } else {
      result = value
    }
  } else if (value instanceof Array) {
    result = []
    let index = 0
    value.forEach(ele => {
      index = findArray(dic, ele)
      if (index != -1) {
        result.push(dic[index].label)
      } else {
        result.push(value)
      }
    })
    result = result.toString()
  }
  return result
}
复制代码

生成随机len位数字

export const randomLenNum = (len, date) => {
  let random = ''
  random = Math.ceil(Math.random() * 100000000000000).toString().substr(0, len || 4)
  if (date) random = random + Date.now()
  return random
}
复制代码

解决ie9不兼容placeholder问题

export function compatiblePlaceholder() {
  if (!('placeholder' in document.createElement('input'))) {
    // 将返回的nodeList对象转为数组
    var nodes = Array.prototype.slice.call(document.querySelectorAll('[placeholder]'))
    nodes.forEach(function (item, index) {
      if (item.nextElementSibling) {

      } else {
        item.addEventListener('focus', function () {
          this.nextSibling.style.display = 'none'
        })
        item.addEventListener('blur', function () {
          if (!this.value) {
            this.style.display = 'none'
            this.nextSibling.style.display = 'inline'
          }
        })
        var cloneNode = item.cloneNode()
        // 如果[type='password']类型,则转为text
        if (cloneNode.getAttribute('type').toLowerCase() === 'password') {
          cloneNode.setAttribute('type', 'text')
        }
        cloneNode.setAttribute('value', cloneNode.getAttribute('placeholder'))
        cloneNode.style.display = 'none'
        item.insertAdjacentHTML('afterend', cloneNode.outerHTML)
        item.nextSibling.addEventListener('focus', function () {
          this.style.display = 'none'
          this.previousSibling.style.display = 'inline'
          this.previousSibling.focus()
        })
        if (!item.value) {
          item.style.display = 'none'
          item.nextSibling.style.display = 'inline'
        }
      }

    })
  }
}
复制代码

精度丢失转换(乘法)

export function accMul(arg1, arg2) {
  let m = 0, s1 = arg1.toString(), s2 = arg2.toString();
  try { m += s1.split(".")[1].length } catch (e) { }
  try { m += s2.split(".")[1].length } catch (e) { }
  return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
}
复制代码

节流函数

/**
 * 节流函数,在一段时间内,回调函数只执行一次
 * @param {Function} fun 需要节流的函数
 * @param {number} delay 节流的时间,单位为毫秒
 */
export function throttle(fun, delay) {
  let valid = true;
  return function() {
    let context = this;
    let args = arguments;
    if (!valid) {
      return;
    }
    valid = false;
    setTimeout(() => {
      fn.apply(context, args);
      valid = true;
    }, delay);
  }
}
复制代码

防抖函数

/**
*防抖函数,多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行
*@param fn 事件触发的操作
*@param delay 多少毫秒内连续触发事件,不会执行
*@returns {Function}
*/
function debounce(fn, delay){
    let timer = null; //借助闭包
    return function(){
      let context = this,
          args = arguments;
      timer && clearTimeout(timer);
      timer = setTimeout(function(){
        fn.apply(context, args);
      },delay);
    } 
}
复制代码

计算时间和当前时间的差值

export const spaceTime = function (atime) {
  atime = atime.replace(/-/g, '/'); //IE出现兼容问题,带“-”格式的时间无法被new Date()转成时间格式,返回NaN.
  let byTime = [365 * 24 * 60 * 60 * 1000, 24 * 60 * 60 * 1000, 60 * 60 * 1000, 60 * 1000, 1000];
  let unit = ["年", "天", "小时", "分钟", "秒钟"];
  var ct = new Date().getTime() - new Date(atime).getTime();
  if (ct <= 1000) {
    // return "时间数据出错!"
    return "刚刚"
  }
  var sb = [];
  for (var i = 0; i < byTime.length; i++) {
    if (ct < byTime[i]) {
      continue;
    }
    var temp = Math.floor(ct / byTime[i]);
    ct = ct % byTime[i];
    if (temp > 0) {
      sb.push(temp + unit[i]);
    }


    /*一下控制最多输出几个时间单位:
        一个时间单位如:N分钟前
        两个时间单位如:M分钟N秒前
        三个时间单位如:M年N分钟X秒前
    以此类推
    */
    if (sb.length >= 1) {
      break;
    }
  }
  return (sb.join("") + "前");
}
复制代码

获取当前年月

export const getNowFormatDate = function() {
  var date = new Date();
  var seperator1 = "-";
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var strDate = date.getDate();
  if (month >= 1 && month <= 9) {
      month = "0" + month;
  }
  if (strDate >= 0 && strDate <= 9) {
      strDate = "0" + strDate;
  }
  var currentdate = year + seperator1 + month;
  return currentdate;
}
复制代码

获取指定时间年月日

export const getFormatDate = function(data) {
  var date = new Date(data);
  var seperator1 = "-";
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var strDate = date.getDate();
  if (month >= 1 && month <= 9) {
      month = "0" + month;
  }
  if (strDate >= 0 && strDate <= 9) {
      strDate = "0" + strDate;
  }
  var currentdate = year + seperator1 + month+strDate;
  return currentdate;
}
复制代码

获取距离当前时间多久的时间

/**
 * 获取距离当前时间多久的时间
 * @param type year年/month月/week周/day日 
 * @param number -为之前/+为之后
 */
export const getBeforAfterTime = function(type=null,number=0) {
  var nowdate = new Date();
  switch (type) {
      case "day":   //取number天前、后的时间
          nowdate.setTime(nowdate.getTime() + (24 * 3600 * 1000) * number);
          var y = nowdate.getFullYear();
          var m = nowdate.getMonth() + 1;
          var d = nowdate.getDate();
          var retrundate = y + '/' + m + '/' + d;
          break;
      case "week":  //取number周前、后的时间
          nowdate.setTime(nowdate.getTime() + (7 * 24 * 3600 * 1000) * number);
          var y = nowdate.getFullYear();
          var m = nowdate.getMonth() + 1;
          var d = nowdate.getDate();
          var retrundate = y + '/' + m + '/' + d;
          break;
      case "month":  //取number月前、后的时间
          nowdate.setMonth(nowdate.getMonth() + number);
          var y = nowdate.getFullYear();
          var m = nowdate.getMonth() + 1;
          var d = nowdate.getDate();
          var retrundate = y + '/' + m + '/' + d;
          break;
      case "year":  //取number年前、后的时间
          nowdate.setFullYear(nowdate.getFullYear() + number);
          var y = nowdate.getFullYear();
          var m = nowdate.getMonth() + 1;
          var d = nowdate.getDate();
          var retrundate = y + '/' + m + '/' + d;
          break;
      default:     //取当前时间
          var y = nowdate.getFullYear();
          var m = nowdate.getMonth() + 1;
          var d = nowdate.getDate();
          var retrundate = y + '/' + m + '/' + d;
  }
  return retrundate;
}
复制代码

正则校验篇

邮箱

export function isEmail (s) {
  return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s)
}
复制代码

手机号码

export function isMobile (s) {
  return /^1[0-9]{10}$/.test(s)
}
复制代码

电话号码

export function isPhone (s) {
  return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
}
复制代码

匹配腾讯QQ号

export function isQQ (s) {
  return /[1-9][0-9]{4,}/.test(s)
}
复制代码

URL地址

export function isURL (s) {
  return /^http[s]?:\/\/.*/.test(s)
}
复制代码

合法uri

export function validateURL (textval) {
  const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
  return urlregex.test(textval)
}
复制代码

小写字母

export function validateLowerCase (str) {
  const reg = /^[a-z]+$/
  return reg.test(str)
}
复制代码

大写字母

export function validateUpperCase (str) {
  const reg = /^[A-Z]+$/
  return reg.test(str)
}
复制代码

大小写字母

export function validatAlphabets (str) {
  const reg = /^[A-Za-z]+$/
  return reg.test(str)
}
复制代码

验证pad还是pc

export const vaildatePc = function () {
  const userAgentInfo = navigator.userAgent
  const Agents = ['Android', 'iPhone',
    'SymbianOS', 'Windows Phone',
    'iPad', 'iPod'
  ]
  let flag = true
  for (var v = 0; v < Agents.length; v++) {
    if (userAgentInfo.indexOf(Agents[v]) > 0) {
      flag = false
      break
    }
  }
  return flag
}
复制代码

判断姓名是否正确

export function validatename (name) {
  var regName = /^[\u4e00-\u9fa5]{2,4}$/
  if (!regName.test(name)) return false
  return true
}
复制代码

匹配8-16位数字和字母密码的正则表达式

export function validatePwd (pwd) {
  var regName = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$/
  if (!regName.test(pwd)) return false
  return true
}
复制代码

密码匹配(至少数字、字母、特殊符号两组组合)

export function validatePwd (pwd) {
  var regName = /(^(?![A-Z]+$)(?![a-z]+$)(?!\d+$)(?![\W_]+$)\S+$)/
  if (!regName.test(pwd)) return false
  return true
}
复制代码

密码匹配(密码由8位数字、大小写字母和特殊符号组成!)

export function validatePwd (pwd) {
  var regName =  /(^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$)/
  if (!regName.test(pwd)) return false
  return true
}
复制代码

判断是否为整数

export function validatenum (num, type) {
  let regName = /[^\d.]/g
  if (type == 1) {
    if (!regName.test(num)) return false
  } else if (type == 2) {
    regName = /[^\d]/g
    if (!regName.test(num)) return false
  }
  return true
}
复制代码

判断是否为小数

export function validatenumord (num, type) {
  let regName = /[^\d.]/g
  if (type == 1) {
    if (!regName.test(num)) return false
  } else if (type == 2) {
    regName = /[^\d.]/g
    if (!regName.test(num)) return false
  }
  return true
}
复制代码

判断是否为空

export function validatenull (val) {
  if (typeof val === 'boolean') {
    return false
  }
  if (typeof val === 'number') {
    return false
  }
  if (val instanceof Array) {
    if (val.length == 0) return true
  } else if (val instanceof Object) {
    if (JSON.stringify(val) === '{}') return true
  } else {
    if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true
    return false
  }
  return false
}
复制代码

判断身份证号码

export function cardid (code) {
  let list = []
  let result = true
  let msg = ''
  var city = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江 ',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北 ',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏 ',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外 '
  }
  if (!validatenull(code)) {
    if (code.length == 18) {
      if (!code || !/(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(code)) {
        msg = '证件号码格式错误'
      } else if (!city[code.substr(0, 2)]) {
        msg = '地址编码错误'
      } else {
        // 18位身份证需要验证最后一位校验位
        code = code.split('')
        // ∑(ai×Wi)(mod 11)
        // 加权因子
        var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
        // 校验位
        var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2, 'x']
        var sum = 0
        var ai = 0
        var wi = 0
        for (var i = 0; i < 17; i++) {
          ai = code[i]
          wi = factor[i]
          sum += ai * wi
        }
        if (parity[sum % 11] != code[17]) {
          msg = '证件号码校验位错误'
        } else {
          result = false
        }
      }
    } else {
      msg = '证件号码长度不为18位'
    }
  } else {
    msg = '证件号码不能为空'
  }
  list.push(result)
  list.push(msg)
  return list
}
复制代码

我是monkeysoft,你的【三连】就是monkeysoft创作的最大动力,如果本篇文章有任何错误和建议,欢迎大家留言!

文章持续更新,可以微信搜索 【猴哥说前端】关注公众号第一时间阅读。