Skip to content

regexp

判断手机号码

javascript
{
  /**
   * @description 判断手机号码
   * @param {String|Number} tel
   * @returns {Boolean}
   */
  function isPhoneNum(tel) {
    return /^1[34578]\d{9}$/.test(tel)
  }

  /**
   * @description 判断是否为手机号 (百度)
   * @param  {String|Number} tel
   * @returns {Boolean}
   */
  function isPhoneNum(tel) {
    return /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/.test(
      tel
    )
  }

  /**
   * @description 手机号(严谨), 根据工信部2019年最新公布的手机号段
   * @param  {String|Number} tel
   * @returns {Boolean}
   */
  function isPhoneNum(tel) {
    return /^1((3[\d])|(4[5,6,7,9])|(5[0-3,5-9])|(6[5-7])|(7[0-8])|(8[\d])|(9[1,8,9]))\d{8}$/.test(
      tel
    )
  }
}

判断是否为邮箱地址

javascript
{
  /**
   * @description 判断是否为邮箱地址
   * @param {String} email
   * @returns {Boolean}
   */
  function isEmail(email) {
    return /^([a-zA-Z0-9_\-])+@([a-zA-Z0-9_\-])+(\.[a-zA-Z0-9_\-])+$/.test(email)
  }
}

验证身份证号码

javascript
{
  /**
   * @description 验证身份证号码(身份证号码可能为15位或18位,15位为全数字,18位中前17位为数字,最后一位为数字或者X)
   * @param {String} idCard
   * @returns {Boolean}
   */
  function isCardNo(idCard) {
    return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(idCard)
  }

  /**
   * @description 验证身份证号码
   * @param {String} idCard
   * @returns {Boolean}
   */
  function isIDCard(idCard) {
    return /(^\d{8}(0\d|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/.test(
      idCard
    )
  }
}

帐号是否合法

javascript
{
  // 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线组合
  var regx = /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/
}

去除首尾的'/'

javascript
{
  // 去除首尾的'/'
  var str = '/asdf//'
  str = str.replace(/^\/*|\/*$/g, '')
}

去除空格 - trim()

javascript
{
  String.prototype.trim = function () {
    return this.replace(/^\s+/, '').replace(/\s+$/, '')
  }
}

{
  // 正则实现trim()功能
  function myTrim(str) {
    let reg = /^\s+|\s+$/g
    return str.replace(reg, '')
  }
  let str = '    wcd    '
  console.log(myTrim(str)) // wcd
}

日期

javascript
{
  // 判断日期格式是否符合 '2017-05-11'的形式,简单判断,只判断格式
  var regx = /^\d{4}\-\d{1,2}\-\d{1,2}$/

  // 判断日期格式是否符合 '2017-05-11'的形式,严格判断(比较复杂)
  var regx =
    /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/
}

账号相关(用户名-密码)

javascript
{
  // 用户名正则
  var regx1 = /^[a-zA-Z0-9_-]{4,16}$/

  // 密码强度正则,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符
  var regx2 = /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/
}

车牌号正则

javascript
{
  // 车牌号正则
  var regx =
    /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/
}
{
  // 新能源车牌号
  var regx1 =
    /[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))$/

  // 非新能源车牌号
  var regx2 =
    /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/

  // 车牌号(新能源+非新能源)
  var regx3 =
    /^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9 挂学警港澳]{1})$/
}

过滤HTML标签

javascript
{
  // 过滤HTML标签
  var str = '<p>dasdsa</p>nice <br> test</br>'
  var regx = /<[^<>]+>/g
  str = str.replace(regx, '')
}

URL

javascript
{
  // URL正则
  var regx = /^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/

  // 合法uri
  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)
  }

  // 操作URL查询参数
  const params = new URLSearchParams(location.search.replace(/\?/gi, '')) // location.search = "?name=yajun&sex=female"
  params.has('yajun') // true
  params.get('sex') // "female"
}

生成随机HEX色值

javascript
{
  // 生成随机HEX色值
  const RandomColor = () =>
    '#' +
    Math.floor(Math.random() * 0xffffff)
      .toString(16)
      .padEnd(6, '0')
  const color = RandomColor()
  // color => "#f03665"
}

生成星级评分

javascript
{
  // 生成星级评分
  const StartScore = (rate) => '★★★★★☆☆☆☆☆'.slice(5 - rate, 10 - rate)
  const start = StartScore(3)
  // start => "★★★"
}

千位分隔符

javascript
{
  /**
   * @description 千位分隔符(格式化金钱)
   * @param {String|Number} num
   * @returns {string}
   */
  function thousandNum(num) {
    var regx = /\d{1,3}(?=(\d{3})+$)/g
    return (num + '').replace(regx, '$&,') // $&表示与regx相匹配的字符串
  }

  /**
   * @description 千位分隔符(格式化金钱)
   * @param {String|Number} num
   * @returns {string}
   */
  function thousandNum(num) {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  }
  // thousandNum(123456789) => "123,456,789"
}

大小写字母

javascript
{
  /* 小写字母*/
  function validateLowerCase(str) {
    const reg = /^[a-z]+$/
    return reg.test(str)
  }

  /* 大写字母*/
  function validateUpperCase(str) {
    const reg = /^[A-Z]+$/
    return reg.test(str)
  }

  /* 大小写字母*/
  function validatAlphabets(str) {
    const reg = /^[A-Za-z]+$/
    return reg.test(str)
  }
}

判空

javascript
{
  //  判断是否为空
  function validatenull(val) {
    if (typeof val === 'boolean') {
      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
  }
}

下划线命名到驼峰命名

javascript
const strToCamel = (str) => str.replace(/(^|_)(\w)/g, (m, $1, $2) => $2.toUpperCase())

console.log(strToCamel('aa_bb_cc_d_e_f'))

other

localStorage(sessionStorage)

javascript
const localStorage = window.localStorage
const sessionStorage = window.sessionStorage

// 设置localStorage存储数据
export const setLocal = (name, content) => {
  if (!name) return
  if (typeof content !== 'string') {
    content = JSON.stringify(content)
  }
  localStorage.setItem(name, content)
}

// 获取localStorage存储数据
export const getLocal = (name) => {
  if (!name) return
  let value = localStorage.getItem(name)
  if (value !== null) {
    try {
      value = JSON.parse(value)
    } catch (error) {
      value = value
    }
  }
  return value
}

// 删除localStorage存储数据
export const removeLocal = (name) => {
  if (!name) return
  localStorage.removeItem(name)
}

// 设置sessionStorage存储数据
export const setSession = (name, content) => {
  if (!name) return
  if (typeof content !== 'string') {
    content = JSON.stringify(content)
  }
  sessionStorage.setItem(name, content)
}

// 获取sessionStorage存储数据
export const getSession = (name) => {
  if (!name) return
  let value = sessionStorage.getItem(name)
  if (value !== null) {
    try {
      value = JSON.parse(value)
    } catch (error) {
      value = value
    }
  }
  return value
}

// 删除sessionStorage存储数据
export const removeSession = (name) => {
  if (!name) return
  sessionStorage.removeItem(name)
}

解析 URL Params 为对象

javascript
function parseParam(url) {
  const paramsStr = /.+\?(.+)$/.exec(url)[1]
  const paramsArr = paramsStr.split('&')
  let paramsObj = {}

  paramsArr.forEach((param) => {
    // 处理有 value 的参数
    if (/=/.test(param)) {
      // 分割 key 和 value
      let [key, val] = param.split('=')
      // 解码
      val = decodeURIComponent(val)
      // 判断是否转为数字
      val = /^\d+$/.test(val) ? parseFloat(val) : val
      // 如果对象有 key,则添加⼀个值
      if (paramsObj.hasOwnProperty(key)) {
        paramsObj[key] = [].concat(paramsObj[key], val)
      } else {
        // 如果对象没有这个 key,创建 key 并设置值
        paramsObj[key] = val
      }
    } else {
      // 处理没有 value 的参数
      paramsObj[param] = true
    }
  })
  return paramsObj
}

let url =
  'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled'
parseParam(url)
// {
// 	city: "北京",
// 	enabled: true,
// 	id: [123, 456],
// 	user: "anonymous",
// }

获取URL的中参数

javascript
/**
 * @method 获取URL的中参数
 * @param {*} strUrl
 */
export const getQueryString = (strUrl) => {
  let reg = new RegExp('(^|&)' + strUrl + '=([^&]*)(&|$)', 'i')
  let r = window.location.search.substr(1).match(reg) //获取url中"?"符后的字符串并正则匹配
  let context = ''
  if (r != null) context = r[2]
  reg = null
  r = null
  return context == null || context == '' || context == 'undefined' ? '' : context
}

时间格式化

javascript
/**
 * @method 时间格式化
 * @param {string} time
 * @param {string} format yyyy/mm/dd hh:ii:ss(2019/07/24 09:45:43) yy/m/d hh:ii:ss(19/07/24 09:45:43) yyyy/mm/dd w(2019/07/24 星期三) mm/dd/yyyy(07/24/2019)
 * @returns
 */
export const formatTime = (time, format = 'yyyy-mm-dd') => {
  const d = time ? new Date(time) : new Date()
  const t = (i) => {
    return (i < 10 ? '0' : '') + i
  }

  const year = d.getFullYear()
  const month = d.getMonth() + 1
  const day = d.getDate()
  const hour = d.getHours()
  const minutes = d.getMinutes()
  const seconds = d.getSeconds()
  const weekday = d.getDay()

  return format.replace(
    /(yy){1,2}|m{1,2}|d{1,2}|h{1,2}|i{1,2}|s{1,2}|w{1,2}/gi,
    function (r) {
      switch (r.toUpperCase()) {
        case 'YY':
          return ('' + year).substr(2)
        case 'YYYY':
          return year
        case 'M':
          return month
        case 'MM':
          return t(month)
        case 'D':
          return day
        case 'DD':
          return t(day)
        case 'H':
          return hour
        case 'HH':
          return t(hour)
        case 'I':
          return minutes
        case 'II':
          return t(minutes)
        case 'S':
          return seconds
        case 'SS':
          return t(seconds)
        case 'W':
          return `星期${['日', '一', '二', '三', '四', '五', '六'][weekday]}`
        case 'WW':
          return [
            'Sunday',
            'Monday',
            'TuesDay',
            'Wednesday',
            'Thursday',
            'Friday',
            'Saturday',
          ][weekday]
      }
    }
  )
}

防抖

防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。 代码实现重在清零 clearTimeout。 防抖可以比作等电梯,只要有一个人进来,就需要再等一会儿。 业务场景有避免登录按钮多次点击的重复提交。

ts
/**
 * @description 函数防抖
 * @param {Function} method 延时调用函数
 * @param {Number} wait 延迟时长
 * @param {Boolean} immediate 立即执行选项
 */
export const Ddebounce = <T extends (...args: any[]) => any>(
  method: T,
  wait: number,
  immediate: boolean
) => {
  if (typeof method !== 'function') {
    throw new TypeError('Expected a function')
  }
  let timeout: ReturnType<typeof setTimeout> | null = null
  // Ddebounce函数为返回值
  // 使用Async/Await处理异步,如果函数异步执行,等待setTimeout执行完,拿到原函数返回值后将其返回
  // args为返回函数调用时传入的参数,传给method
  let Ddebounce = async (...args: Parameters<T>): Promise<ReturnType<T>> => {
    return new Promise((resolve) => {
      // 用于记录原函数执行结果
      let result: ReturnType<T>
      // 将method执行时this的指向设为 debounce 返回的函数被调用时的this指向
      let context = this
      // 如果存在定时器则将其清除
      if (timeout) {
        clearTimeout(timeout)
      }
      // 立即执行需要两个条件,一是immediate为true,二是timeout未被赋值或被置为null
      if (immediate) {
        // 如果定时器不存在,则立即执行,并设置一个定时器,wait毫秒后将定时器置为null
        // 这样确保立即执行后wait毫秒内不会被再次触发
        let callNow = !timeout
        timeout = setTimeout(() => {
          timeout = null
        }, wait)
        // 如果满足上述两个条件,则立即执行并记录其执行结果
        if (callNow) {
          result = method.apply(context, args)
          resolve(result)
        }
      } else {
        // 如果immediate为false,则等待函数执行并记录其执行结果
        // 并将Promise状态置为fullfilled,以使函数继续执行
        timeout = setTimeout(() => {
          // args是一个数组,所以使用fn.apply
          // 也可写作method.call(context, ...args)
          result = method.apply(context, args)
          resolve(result)
        }, wait)
      }
    })
  }

  // 在返回的 Ddebounce 函数上添加取消方法
  // Ddebounce.cancel = function () {
  //   clearTimeout(timeout)
  //   timeout = null
  // }
  return Ddebounce
}

节流

节流:控制流量,单位时间内事件只能触发一次,与服务器端的限流 (Rate Limit) 类似。 代码实现重在开锁关锁 timer=timeout; timer=null。 节流可以比作过红绿灯,每等一个红灯时间就可以过一批。

ts
/**
 * 节流
 * @param func 回调函数
 * @param delay 延迟时间
 */
export const Dthrottle = <T extends (...args: any[]) => void>(func: T, delay: number) => {
  let timer: ReturnType<typeof setTimeout> | null = null

  return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
    const context = this

    if (!timer) {
      timer = setTimeout(function () {
        func.apply(context, args)
        timer = null
      }, delay)
    }
  }
}

数组扁平化

javascript
/**
 * @method 数组扁平化
 * @param {*} arry
 */
export const deepFlatten = (arr) => {
  return arr
    .toString()
    .split(',')
    .map((item) => +item)
  // or
  // return [].concat(...arr.map(item => (Array.isArray(item) ? deepFlatten(item) : item)));
}

判断类型

javascript
/**
 * @method 判断类型
 * @param {*} obj
 * @returns
 */
export const toType = (obj) => {
  return {}.toString
    .call(obj)
    .match(/\s([a-zA-Z]+)/)[1]
    .toLowerCase()
}

html 转义

javascript
export const escapeHtml = (str) => {
  if (!str) return
  str = str.replace(/&/g, '&amp;')
  str = str.replace(/</g, '&lt;')
  str = str.replace(/>/g, '&gt;')
  str = str.replace(/“/g, '&quto;')
  str = str.replace(/'/g, '&#39;')
  return str
}

等待一定时间后执行

javascript
const wait = async (milliseconds) =>
  new Promise((resolve) => setTimeout(resolve, milliseconds))

判断对象是否为空

javascript
const isEmpty = (obj) => Reflect.ownKeys(obj).length === 0 && obj.constructor === Object

检查函数是否是promise

javascript
// 可先看vue源码实现(不严谨,但是够用)
function isDef(v) {
  return v !== undefined && v !== null
}

function isPromise(fn) {
  return isDef(fn) && typeof fn.then === 'function' && typeof fn.catch === 'function'
}

console.log(isPromise(new Promise())) // true

// graphql-js 的实现方式
function isPromise_graphql(fn) {
  return Boolean(fn && typeof fn.then === 'function')
}

// 利用 instanceof
function isPromise_instanceof(fn) {
  return fn instanceof Promise
}

// 利用 prototype
function isPromise_prototype(fn) {
  return fn && Object.prototype.toString.call(fn) === '[object Promise]'
}

检查函数是否是一个生成器

javascript
const test = function* () {
  yield undefined
}

console.log(x.constructor.name === 'GeneratorFunction') // true

// 或者

const GeneratorFunction = function* () {
  yield undefined
}.constructor

console.log(test instanceof GeneratorFunction) // true

// 需要注意
foo = test.bind(bar)
console.log(foo instanceof GeneratorFunction) // false