记录一些有用的函数

480 阅读7分钟

为了需要用到的时候CV😬

浏览器操作(BOM)

获取浏览器类型

/**
 * 
 * @returns {object} 返回一个对象
 */
function browser () {
  // 取得浏览器的userAgent字符串
  var userAgent = navigator.userAgent;
  // 判断是否Opera浏览器
  let isOpera = userAgent.indexOf('Opera') > -1;
  // 判断是否IE浏览器
  let isIE = ((userAgent.indexOf('compatible') > -1) && userAgent.indexOf('MSIE') > -1 && !isOpera) || userAgent.indexOf('Trident') > -1;
  // 判断是否IE的Edge浏览器
  let isEdge = userAgent.indexOf('AppleWebKit') > -1 && userAgent.indexOf('Edge') > -1 && !isIE;
  // 判断是否Firefox浏览器
  let isFF = userAgent.indexOf('Firefox') > -1;
  // 判断是否Safari浏览器
  let isSafari = userAgent.indexOf('Safari') > -1 && userAgent.indexOf('Chrome') === -1;
  // 判断Chrome浏览器
  let isChrome = userAgent.indexOf('Chrome') > -1 && userAgent.indexOf('Safari') > -1;
  let obj = {
    chrome: isChrome,
    firefox: isFF,
    safari: isSafari,
    opera: isOpera,
    edge: isEdge,
    ie: isIE,
    mobile: !!userAgent.match(/AppleWebKit.*Mobile.*/), // 是否为移动终端
    ios: !!userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), // ios终端
    android: userAgent.indexOf('Android') > -1 || userAgent.indexOf('Adr') > -1, // android终端
    iPhone: userAgent.indexOf('iPhone') > -1, // 是否为iPhone或者QQHD浏览器
    iPad: userAgent.indexOf('iPad') > -1, // 是否iPad
    webApp: userAgent.indexOf('Safari') === -1, // 是否web应该程序,没有头部与底部
    weixin: userAgent.indexOf('MicroMessenger') > -1, // 是否微信 (2015-01-22新增)
    qq: userAgent.match(/\sQQ/i) == ' qq', // 是否QQ
  };

  if (isIE) {
    var reIE = new RegExp('MSIE (\\d+\\.\\d+);');
    reIE.test(userAgent);
    var fIEVersion = parseFloat(RegExp['$1']);
    obj.ieVersion = fIEVersion;
    // ie 11
    if (userAgent.indexOf('Trident') > -1 && /rv:(\w+)/.test(userAgent)) {
      obj.ieVersion = RegExp.$1;
    }
  }
  return obj;
}

获取url的base url

/**
 * 根据指定url或当前页面的url,获取url的base url
 * @param _url url地址,可选
 * @returns {string}
 */
function getBaseUrl(_url) {
  let aEle = document.createElement('a');
  let url = '';
  aEle.href = _url || window.location.href;
  url += aEle.protocol + '//' + aEle.host;
  aEle = null;
  return url;
}

获取ulr的基本信息

/**
 * 获取ulr的基本信息
 * @param _url
 * @returns {{protocol: string, search: string, host: string, hash: string, pathname: string}}
 */
function getUrlInfo(_url) {
  let aEle = document.createElement('a');
  aEle.href = _url || window.location.href;
  let obj = {
    protocol: aEle.protocol,
    host: aEle.host,
    pathname: aEle.pathname,
    search: aEle.search,
    hash: aEle.hash
  };
  return obj;
}

获取url中指定参数的值

/**
 * 获取url中指定参数的值,没有返回 undefined
 * 		https:www.baidu.com?username=lucy
 * 		username:  lucy
 * @param name url参数名称
 * @returns {string | undefined}
 */
function getParams(name) {
  let res = undefined;
  let categoryStr = window.location.href.split('?')[1] || '';
  if (categoryStr.length > 1) {
    let arr = categoryStr.split('&');
    for (let i = 0, len = arr.length; i < len; i++) {
      let pair = arr[i];
      let key = pair.split('=')[0];
      let value = pair.split('=')[1];
      if (key === name) {
        res = value;
        break;
      }
    }
  }
  return res;
}

判断url(网址)是否可以访问

/**
 * 判断url(网址)是否可以访问
 * @param url 网页地址
 * @param timeout 超时时间
 * @returns {Promise<unknown>|boolean}
 */
function urlCanVisit(url, timeout = 10000) {
  if (!url) {
    return false;
  }
  return new Promise((resolve, reject) => {
    let script = document.createElement('script');
    script.type = 'text/javascript';
    if (script.readyState) {   //IE
      script.onreadystatechange = function () {
        if (script.readyState == 'complete' || script.readyState == 'loaded') {
          script.onreadystatechange = null;
          resolve(true);
          document.body.removeChild(script);
          // console.log('加载完成')
        }
      }
    } else {    // 非IE
      script.onload = function (res) {
        // console.log('加载完成',res)
        script.onload = null;
        resolve(true);
        document.body.removeChild(script);
      }
    }
    script.onerror = (e) => {
      // console.log('加载失败', e)
      resolve(false);
      document.body.removeChild(script);
    }
      script.src = url;
      document.body.appendChild(script);
  });
}

获取浏览器宽高

function getDocumentWidthHeight () {
  if (window.innerHeight != null) {
    return {
      width: window.innerWidth,
      height: window.innerHeight,
    };
  } else if (document.compatMode === 'CSS1Compat') {
    // 怪异模式浏览器
  	return {
      width: document.documentElement.scrollWidth,
      height: document.documentElement.scrollHeight,
    };
  }
  return {
    width: document.body.scrollWidth,
    height: document.body.scrollHeight,
  };
}

获取浏览器滚动条的位置

function scrollTop () {
  return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
}

获取元素距浏览器最顶部及最左边的距离

/**
 * 获取元素距浏览器最顶部及最左边的距离
 * 
 * @param ele dom元素
 * @returns @returns {{top: number, left: number}}
 */
function offset (ele) {
  let positon = {
    top: 0,
    left: 0,
  };
  let offsetParent = ele.offsetParent;
  positon.top = ele.offsetTop;
  positon.left = ele.offsetLeft;
  while (offsetParent != null) {
    positon.top += offsetParent.offsetTop;
    positon.left += offsetParent.offsetLeft;
    offsetParent = offsetParent.offsetParent;
  }
  return positon;
}

获取浏览器使用的语言

/**
 * 获取浏览器使用的语言
 */
function getBrowserLang() {
  var type = navigator.appName;
  let lang = '';
  if (type === 'Netscape') {
    // 获取浏览器配置语言,支持非IE浏览器
    lang = navigator.language;
  } else {
    // 获取浏览器配置语言,支持IE5+ == navigator.systemLanguage
    lang = navigator.userLanguage;
  }
  return lang.toLowerCase();
}

获取站点domain

/**
 * 获取站点domain
 * @param href
 * @returns {string}
 */
function getBaseDomain(href) {
  href = href || window.location.href;
  let baseUrl = this.getBaseUrl(href);
  if (/localhost\:/.test(baseUrl)) {
    return 'localhost';
  };
  let arr = baseUrl.split('.');
  arr.shift();
  return arr.join('.');
}

浏览器页面可见性相关操作

const visibility = {
  // 为了能在旧版浏览器中获取到document.hidden,需要加前缀处理
  getHiddenProp() {
    var prefixes = ['webkit', 'moz', 'ms', 'o'];
    if ('hidden' in document) return 'hidden';
    for (var i = 0, len = prefixes.length; i < len; i++) {
      if ((prefixes[i] + 'Hidden') in document) {
        return prefixes[i] + 'Hidden';
      }
    }
    return null;
  },
  // 获取不同浏览器的的visibility state属性名称,有加前缀
  getVisibilityState() {
    var prefixes = ['webkit', 'moz', 'ms', 'o'];
    if ('visibilityState' in document) return 'visibilityState';
    for (var i = 0; i < prefixes.length; i++) {
      if ((prefixes[i] + 'VisibilityState') in document) {
        return prefixes[i] + 'VisibilityState';
      }
    }
    return null;
  },
  // 获取不同浏览器的visibility事件名称
  getVisibilityChangeEventName() {
    let prop = this.getHiddenProp();
    if (!prop) {
      return null;
    }
    return prop.replace(/[H|h]idden/, '') + 'visibilitychange';
  },
  // 获取页面是否可见
  isHidden() {
    var prop = this.getHiddenProp();
    if (!prop) return false;
    return document[prop];
  },
}

DOM操作

给指定元素添加class

 /**
 * 给指定元素添加class
 * 
 * @param ele dom元素
 * @param classname {string} class类名
 * @returns ele 添加class后的元素
 */
function addClass (ele, classname) {
  if (!ele || !classname || ele.nodeType !== 1) {
    return;
  }
  let classArr = classname.split(' ');
  if (ele.classList) {
    for (var i = 0, len = classArr.length; i < len; i++) {
      let item = classArr[i];
      if (!ele.classList.contains(item)) {
        ele.classList.add(item);
      }
    }
    return ele;
	} else {
      let classNameArr = ele.className && ele.className.length > 0 ? ele.className.split(' ') : [];
      if (classNameArr.length === 0) {
        ele.className = classname;
        return;
      }
      // 合并两个数组
      Array.prototype.push.apply(classNameArr, classArr);
      classNameArr = tool.arrayNoReapeat(classNameArr);
      ele.className = classNameArr.join(' ');
      return ele;
	}
}

给指定元素移除class

/**
 * 给指定元素移除class
 * 
 * @param ele dom元素
 * @param classname {string} 要移除的类名
 * @returns ele 移除类名后的dom元素
 */
function removeClass (ele, classname) {
  if (!ele || !classname || ele.nodeType !== 1) {
    return;
  }
  let classArr = classname.split(' ');
  if (ele.classList) {
    for (var i = 0, len = classArr.length; i < len; i++) {
      let item = classArr[i];
      if (ele.classList.contains(item)) {
      	ele.classList.remove(item);
      }
    }
    return ele;
  } else {
      let classNameArr = ele.className && ele.className.length > 0 ? ele.className.split(' ') : [];
      if (classNameArr.length === 0) {
          return;
      }
      for (var i = classNameArr.length; i >= 0; i--) {
        for (var j = 0, len2 = classArr.length; j < len2; j++) {
          if (classNameArr[i] === classArr[j]) {
            classNameArr.splice(i, 1);
          }
        }
      }
      ele.className = classNameArr.join(' ');
      return ele;
	}
}

判断元素是否包含指定className

/**
 * 判断元素是否包含指定className
 * 
 * @param ele dom元素
 * @param className className
 * @returns {boolean}
 */
function hasClass (ele, className) {
  if (!ele || !ele.nodeName) {
    console.error('ele 必须是一个dom元素');
    return;
  }
  if (!className) {
    console.error('className 必须是一个字符串');
    return;
  }
  if (ele.classList) {
    return ele.classList.contains(className);
  } else {
    let flag = false;
    let classNameArr = ele.className.split(' ');
    for (let i = 0, len = classNameArr.length; i < len; i++) {
    if (classNameArr[i] === className) {
      flag = true;
      break;
    }
  }
  return flag;
  }
}

获取元素的css属性值

/**
 * 获取元素的css属性值
 * @param ele dom元素
 * @param cssAttribute css属性名称
 */
function getStyle (ele, cssAttribute) {
  if (!ele || !ele.nodeName) {
    console.error('ele 必须是一个dom元素');
    return;
  }
  if (!cssAttribute) {
    console.error('cssAttribute 必须是一个字符串');
    return;
  }
  let val = '';
  if (window.getComputedStyle) {
    val = window.getComputedStyle(ele, null)[cssAttribute];
  } else if (ele.currentStyle) {
    val = ele.currentStyle[cssAttribute];
  }
  if (!isNaN(parseFloat(val))) {
    return parseFloat(val);
  } else {
    return val;
  }
},

给元素设置css属性

/**
 * 给元素设置css属性
 * @param ele dom元素
 * @param attr css属性名
 * @param val css属性值,如果不传递attr参数,则该参数可以为一个对象,就像jquery的css()方法一样
 */
function setCss (ele, attrs, val) {
  if (!ele || !ele.nodeName) {
    console.error('ele 必须是一个dom元素');
    return;
  }
  let type1 = ({}).toString.call(attrs);
  // 需要字段加单位的css属性
  let autoAddUnitAttr = {
      width: 1,
      height: 1,
      margin: 1,
      padding: 1,
      borderRadius: 1,
      top: 1,
      left: 1,
      marginLeft: 1,
      marginRight: 1,
      marginTop: 1,
      marginBottom: 1,
      right: 1,
      bottom: 1,
      paddingLeft: 1,
      paddingRight: 1,
      paddingTop: 1,
      paddingBottom: 1,
      borderTopLeftRadius: 1,
      borderTopRightRadius: 1,
      borderBottomLeftRadius: 1,
      borderBottomRightRadius: 1,
      fontSize: 1,
      lineHeight: 1,
      textIndent: 1,
      minWidth: 1,
      maxWith: 1,
  };
  if (type1 === '[object String]' && typeof val !== 'undefined') {
    attrs = attrs.replace(/\-(\w)/g, function (matched, $1) {
      return $1.toUpperCase();
    });
    if (attrs in autoAddUnitAttr && !isNaN(Number(val))) {
      ele.style[attrs] = val + 'px';
    } else {
      ele.style[attrs] = val;
    }
  } else if (type1 === '[object Object]') {
	let style = ele.style;
	for (let attr in attrs) {
      let val2 = attrs[attr];
      let isNumber = Number(val2);

      attr = attr.replace(/\-(\w)/g, function (matched, $1) {
      	return $1.toUpperCase();
      });

      if (attr in autoAddUnitAttr && !isNaN(isNumber)) {
      	style[attr] = val2 + 'px';
      } else {
      	style[attr] = val2;
      }
  	}
  }
  return this;
}

获取兄弟节点

/**
 * 获取兄弟节点
 * @param elm
 * @returns {Array}
 */
function siblings (elm) {
  let a = [];
  let p = elm.parentNode.children;
  for (let i = 0, pl = p.length; i < pl; i++) {
    if (p[i] !== elm) a.push(p[i]);
  }
  return a;
}

判断两个元素是否是包含关系

/**
 * 判断两个元素是否是包含关系
 * @param ele 父元素
 * @param childEle 子元素
 * @returns {Boolean}
 */
function elementContains (ele, childEle) {
  if (ele === childEle) {
    return false;
  }
  if (typeof ele.contains === 'function') {
    return ele.contains(childEle);
  } else {
    while (true) {
      if (!childEle) {
        return false;
      }
      if (childEle === ele) {
        return true;
      } else {
        childEle = childEle.parentNode;
      }
    }
    return false;
  }
}

将滚动条滚动到指定元素所在位置

/**
 * 将滚动条滚动到指定元素所在位置
 * @param ele dom元素
 * @param extraTop 额外的高度,比如在元素的位置基础上加10px,或减10px
 * @param autofocus 如果是表单元素的话是否滚动完后自动获得焦点
 */
function scrollToElement (ele, extraTop, autofocus) {
  if (!ele || !ele.nodeName) {
    console.error('ele 必须是一个dom元素');
    return;
  }
  autofocus = !!autofocus;
  let top = ele.offsetTop;
  let offsetParent = ele.offsetParent;

  while (offsetParent != null) {
    top += offsetParent.offsetTop;
    offsetParent = offsetParent.offsetParent;
  }
  top += extraTop;
  window.scrollTo(0, top);

  if (autofocus && ele.focus) {
    ele.focus();
  }
  return this;
}

绑定事件

/**
 * 绑定事件
 * @param ele dom元素
 * @param eventName 事件名称
 * @param fn 事件回调函数
 */
function on (ele, eventName, fn) {
  if (!ele) {
    console.error('on(ele, eventName, fn)函数第一个参数必须是一个dom元素!');
    return this;
  }
  if (!eventName || typeof eventName !== 'string') {
    console.error('on(ele, eventName, fn)函数第二个参数必须是一个字符串!');
    return this;
  }
  if (!fn || typeof fn !== 'function') {
    console.error('on(ele, eventName, fn)函数第三个参数必须是一个函数!');
    return this;
  }
  if (!ele._events) {
    ele._events = {};
  }

  if (!(eventName in ele._events)) {
    ele._events[eventName] = [fn];
    if (document.addEventListener) {
        var eventFn = function (e) {
            var events = ele._events[eventName];
            if (events && events.length > 0) {
                for (var i = 0, len = events.length; i < len; i++) {
                  if (events[i]) {
                      events[i].call(ele, e);
                  }
                }
            }
        };
        ele.addEventListener(eventName, eventFn, false);
        // 把事件回调函数也存起来,这样在移除事件的时候才能真正的把该事件移除掉
        ele._events[eventName + '_fn'] = eventFn;
      } else if (window.attachEvent) {
        var eventFn = function () {
          var events = ele._events[eventName];
          var e = window.event;
          e.preventDefault = function () {
            e.returnValue = false;
          };
          e.stopPropagation = function () {
            e.cancelBubble = true;
          };
          for (var i = 0, len = events.length; i < len; i++) {
            events[i].call(ele, e);
          }
        };
        ele.attachEvent('on' + eventName, eventFn);
        ele._events[eventName + '_fn'] = eventFn;
      }
  } else {
    //ele._events[eventName] = [fn];
    var index = this.getIndex(ele._events[eventName], function (item) {
      return item === fn;
    });
    if (index < 0 || typeof index === 'undefined') {
      ele._events[eventName].push(fn);
    }
  }
  return this;
}

解绑事件

/**
 * 解绑事件
 * @param ele dom元素
 * @param eventName 事件名称
 * @param fn 事件回调函数
 */
function off (ele, eventName, fn) {
  if (!ele) {
    console.error('off(ele, eventName, fn)函数第一个参数必须是一个dom元素!');
    return;
  }
  if (!eventName || typeof eventName !== 'string') {
    console.error('off(ele, eventName, fn)函数第二个参数必须是一个字符串!');
    return;
  }
  if (!ele._events) {
    return this;
  }
  if (!eventName) {
    return this;
  }

  var events = ele._events[eventName];
  var eventFn = ele._events[eventName + '_fn'];
  
  // 如果只传递了事件名称而未传递具体的事件,则将指定事件名称的所有回调函数全部清除
  if (eventName && !fn) {
    if (document.removeEventListener) {
      ele.removeEventListener(eventName, eventFn, false);
    } else if (window.detachEvent) {
      ele.detachEvent('on' + eventName, eventFn);
    }
    delete ele._events[eventName];
    delete ele._events[eventName + '_fn'];
  } else if (eventName && fn) {
    if (!events) {
      return;
    }
    if (document.removeEventListener) {
      var index = this.getIndex(events, function (item) {
        return item === fn;
      });
      if (index > -1) {
        events.splice(index, 1);
      }
      if (events.length === 0) {
        delete ele._events[eventName];
        delete ele._events[eventName + '_fn'];
      }
    } else if (window.detachEvent) {
      if (!events) {
        return;
      }
      var index = this.getIndex(events, function (item) {
        return item === fn;
      });
      if (index > -1) {
        events.splice(index, 1);
      }
      if (events.length === 0) {
        delete ele._events[eventName];
        delete ele._events[eventName + '_fn'];
      }
    }
  }
  events = null;
  return this;
}

获取元素的指定父级元素

/**
 * 获取元素的指定父级元素
 * @param el dom 元素
 * @param className 父元素的class name
 * @returns {dom、undefined}
 */
function parents(el, className) {
  if (!el || !el.nodeName || !className) {
    return;
  }
  var classNameArr = className.split(' ');
  var parent = el.parentElement;

  while (parent) {
    var flag = true;
    for (var i = 0, len = classNameArr.length; i < len; i++) {
      if (!this.hasClass(parent, classNameArr[i])) {
        flag = false;
        break;
      }
    }
    if (flag) {
      return parent;
    } else {
      parent = parent.parentElement;
    }
  }
}

数组操作

数组去重

/**
 * 数组去重
 * @param arr 需要去重的数组
 * @param isObjectValue 数组的值是否是引用类型
 * @returns {Array} 去重后的数组
 */
function arrayNoReapeat(arr, isObjectValue) {
  if (!arr || arr.length === 0) {
    return arr;
  }
  isObjectValue = typeof isObjectValue === 'undefined' ? false : !!isObjectValue;
  var arrLen = arr.length;
  let newArr = [];
  // 值类型的数组,使用对象属性唯一的特性来去重
  if (!isObjectValue) {
    var obj = {};
    for (var i = 0; i < arrLen; i++) {
      obj[arr[i]] = 1;
    }
    for (var attr in obj) {
      newArr.push(attr);
    }
    return newArr;
  }
  
  newArr.push(arr[0]);
  
  for (var i = 1; i < arrLen; i++) {
    let item = arr[i];
    let repeat = false;
    for (var j = 0; j < newArr.length; j++) {
      if (item === arr[j]) {
        repeat = true;
        break;
      }
    }
    if (!repeat) {
      newArr.push(item);
    }
  }
	return newArr;
}

转换数组中的对象

/**
 * 转换数组中的对象,如:
 * convertObjectInArr([{id: 1,name: "张三"},{id: 2,name: "李四"}], {id: "value", name: "text"}, true)
 *  => [{value: 1,text: "张三"},{value: 2,text: "李四"}]
 * @param arr {Array} 需要转换的数组
 * @param obj {Object} 一个对象
 * @param delOriginAttr {Boolean} 是否删除原来的属性(可选)默认值删除原理属性
 * @return arr {Array} 返回转换后的数组
 */
function convertObjectInArr(arr, obj, delOriginAttr=true) {
  if (!arr || arr.length === 0) {
    return arr;
  }
  arr.forEach((item) => {
    // eslint-disable-next-line
    for (let attr in item) {
      for (let origin in obj) {
        if (origin in item) {
          item[obj[origin]] = item[origin];
          // eslint-disable-next-line
          if (!!delOriginAttr) {
            delete item[origin];
          }
        }
      }
    }
  });
  return arr;
}

数组累加器

/**
 * 数组累加器,根据一个数组返回累加后的数组
 * 算法:原始arr1
 *      return [arr[0], arr[0]+arr[0], arr[0]+arr[1]+arr[2], ...];
 * @param seriesArr {Array}
 * @returns {Array} 累加后的数组
 */
function arrayAccumulate(seriesArr) {
  if (({}).toString.call(seriesArr) !== '[object Array]') {
    return seriesArr;
  }
  if (seriesArr.length === 1) {
    return seriesArr;
  }
  // 用于存储每一步计算的结果
  let cache = {};
  let resultArr = [];
  seriesArr.forEach((item, index) => {
    if (index === 0) {
      resultArr.push(item);
      cache[index] = item;
    } else {
      let sum = 0;
      // 如果前一个索引的值在缓存中,则从缓存中取
      if (((index - 1) + '') in cache) {
          sum = cache[index - 1] + item;
      } else {
        // 如果前一个索引不在缓存中,则直接循环计算
        for (var i = 0; i <= index; i++) {
          sum += seriesArr[i];
        }
      }
      resultArr.push(sum);
      // 将当前索引及值添加到缓存中,以备后续使用
      cache[index] = sum;
    }
  });
  cache = null;
  return resultArr;
}

获取数组中符合条件的元素的索引

/**
 * 获取数组中符合条件的元素的索引
 * @param arr 数组
 * @param fn 一个函数,如果函数返回true,则返回该项的下标,如果没有找到则返回-1
 * @returns {number} 符合条件的元素的索引
 */
function  getIndex(arr, fn) {
  if (!arr || arr.length === 0 || !fn || (typeof fn !== 'function')) {
    return -1;
  }

  if (arr.findIndex) {
    return arr.findIndex(fn);
  }
  let len = arr.length;
  let i = 0;
  let index = -1;
  for (; i < len; i++) {
    let item = arr[i];
    if (fn(item, index, arr) === true) {
      index = i;
      break;
    }
  }
  return index;
}

对象操作

判断对象是否是一个空对象 (简单模式)

/**
 * 判断对象是否是一个空对象
 * @param obj
 */
function isEmptyObject(obj) {
  for (var attr in obj) {
    return false;
  }
  return true;
}

清空一个对象的数据,默认将对象中的每一项的值都设为空

/**
 * 清空一个对象的数据,默认将对象中的每一项的值都设为空
 * 如:clearData({name: "张三", age: 23}) => {name: "", age: ""}
 *     clearData({name: "张三", age: 23}, {age: 0}) => {name: "", age: 0}
 * @param datas
 * @param specially
 * @returns {Object}
 */
function clearData(datas, specially) {
  if (!datas || ({}).toString.call(datas) !== '[object Object]') {
    return;
  }
  if (!specially) {
    specially = {};
  }
  for (var attr in datas) {
    if (attr in specially) {
      datas[attr] = specially[attr];
    } else {
      datas[attr] = '';
    }
  }
  return datas;
}

各种格式化

格式化手机号

/**
 * 格式化手机号
 * 如:
 * formatPhone("12345678910", "start") => ****5678910
 * formatPhone("12345678910", "center") => 123****8910
 * formatPhone("12345678910", "end") => 1234567****
 * @param phone 手机号
 * @param format 格式,可选值有:start、center、end
 * @param count 格式化多少个字符,默认4个
 * @returns {string}
*/
function formatPhone(phone, format = 'center', count) {
  phone = phone + '';
  let len = phone.length;
  let arr = phone.split('');
  let start = 0;
  let end = 0;
  let replacement = '***********************';

  if (format === 'start') {
    if (typeof count === 'undefined') {
      count = 4;
    }
    if (count >= len) {
      count = len - 2;
    }
    arr.splice(0, count, replacement.substr(0, count));
    return arr.join('');
  }
  if (format === 'center') {
    if (typeof count === 'undefined') {
      count = 4;
    }
    if (count >= len) {
      count = len - 2;
    }
    start = Math.floor((len - count) / 2);
    end = count;
    arr.splice(start, end, replacement.substr(0, count));
    return arr.join('');
  }
  if (format === 'end') {
    if (typeof count === 'undefined') {
      count = 4;
    }
    if (count >= len) {
      count = len - 2;
    }
    arr.splice(len - count, len, replacement.substr(0, count));
    return arr.join('');
  }
}

格式化邮箱

/**
 * 格式化邮箱
 * 如:
 * 	formatEmail("123456789@qq.com") => 12*****89@qq.com
 *	formatEmail("abc@qq.com") => a*c@qq.com
 *	formatEmail("abc123@qq.com") => a*****@qq.com
 *	formatEmail("abc12@qq.com") => a***2@qq.com
 *	formatEmail("a@qq.com") => *@qq.com
 * @param email 邮箱
 * @param maxCount 最大截取长度,默认5
 * @returns {string}
*/
function formatEmail(email, maxCount = 5) {
  let emailReg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
  if (!email || !emailReg.test(email)) {
      return email;
  }
  if (typeof maxCount === 'string' || maxCount <= 0) {
      maxCount = 5;
  }
  let emailLeft = email.split('@')[0];
  let emailRight = email.split('@')[1];
  let leftResult = '';
  let emailLeftLen = emailLeft.length;
  if (emailLeftLen === 1) {
      leftResult = '*';
  } else {
  	/* 如果邮箱名长度小于等于最大截取长度,则只留第一个及最后一个字符。效果:abcd@123.com => a**d@123.com */
    if (emailLeftLen <= maxCount) {
        let len = emailLeftLen;
        while (len > 0) {
            leftResult += '*';
            len--;
        }
        leftResult = leftResult.split('');

        leftResult[0] = emailLeft.charAt(0);
        leftResult[emailLeftLen - 1] = emailLeft.charAt(emailLeftLen - 1);
    } else {
        /* 如果邮箱名长度大于最大截取长度,则将邮箱名中间的替换成"*" */
        let startIndex = Math.ceil((emailLeftLen - maxCount) / 2);
        let endIndex = startIndex + maxCount;
        leftResult = emailLeft.split('');

        if (endIndex > emailLeftLen) {
            endIndex = emailLeftLen - 1;
        }
        for (; startIndex < endIndex; startIndex++) {
            leftResult[startIndex] = '*';
        }
    }
    leftResult = leftResult.join('');
  }
  return leftResult + '@' + emailRight;
}

格式化日期

/**
 * 格式化日期
 * 如:
 *  formatDate(new Date) => 2018-07-27 14:32:25
 *  formatDate(1532673162672) => 2018-07-27 14:32:25
 *  formatDate("abc1532673162672def") => 2018-07-27 14:32:25
 *  formatDate(new Date, "yyyy年MM月dd日 hh时mm分ss秒") => 2018年07月27日 14时32分25秒
 * @param dateTemp
 * @param format
 * @returns {string}
 */
function formatDate(dateTemp, format = 'yyyy-MM-dd hh:mm:ss') {
  if (typeof dateTemp === 'undefined' || dateTemp === null) {
    console.error('dateTemp不是一个合法的值,dateTemp可以为:时间戳、日期时间字符串、Date对象');
    return;
  }
  if (typeof dateTemp === 'object' && !(/Date/.test(({}).toString.call(dateTemp)))) {
    console.error('dateTemp不是一个Date对象,请检查dateTemp数据类型!');
    return;
  }
  let date;
  if (typeof dateTemp !== 'object') {
    let dateStr = dateTemp + '';
    dateStr = /\d{13,}/.exec(dateStr);
    if (!dateStr) {
      date = new Date(dateTemp.replace(/\-/g, '/'));
    } else {
      date = new Date(dateStr * 1);
    }
  } else {
    date = dateTemp;
  }
  if (/(y{0,4})/.test(format)) {
      format = format.replace(/y{0,4}/, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  }
  let obj = {
      'M+': (date.getMonth() + 1 + ''),
      'd+': (date.getDate() + ''),
      'h+': (date.getHours() + ''),
      'm+': (date.getMinutes() + ''),
      's+': (date.getSeconds() + ''),
  };
  for (let attr in obj) {
    if (new RegExp('(' + attr + ')').test(format)) {
        format = format.replace(new RegExp(attr), tool.padStartZero(obj[attr]).substr(2 - RegExp.$1.length));
    }
  }
  return format;
}

根据指定时间的倒计时功能

/**
 * 根据指定时间的倒计时功能
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param callBack 倒计时每走一次的回调函数
 * @param endedCallback 倒计时结束回调函数
 */
function countDownForTime(endTime, callBack, endedCallback) {
  let timeReg = /^\d+$/;
  if (!timeReg.test(endTime)) {
    console.eror('endTime 必须是一个时间戳!');
    return;
  }
  if (!callBack || typeof callBack !== 'function') {
    console.error('callBack 必须是一个函数!');
    return;
  }
  endTime = endTime * 1;
  let endDate = new Date(endTime);
  let distance = 0;
  let result = {
    day: 0,
    hours: 0,
    minutes: 0,
    seconds: 0,
  };
  let clear = function () {
    clearInterval(timer);
  };
  let timer = setInterval(() => {
    distance = (endDate.getTime() - new Date().getTime()) / 1000;
    if (distance < 0) {
      clearInterval(timer);
      if (endedCallback && typeof endedCallback === 'function') {
        endedCallback(result);
      }
      return;
    }
    let day = Math.floor(distance / 60 / 60 / 24);
    let hours = Math.floor(distance / 60 / 60 % 24);
    let minutes = Math.floor(distance / 60 % 60);
    let seconds = Math.floor(distance % 60);
    result.day = day >= 10 ? day : ('0' + day);
    result.hours = hours >= 10 ? hours : ('0' + hours);
    result.minutes = minutes >= 10 ? minutes : ('0' + minutes);
    result.seconds = seconds >= 10 ? seconds : ('0' + seconds);

    callBack(result, clear);
  }, 1000);
}

清除字符串两端空格,包含换行符、制表符

/**
 * 清除字符串两端空格,包含换行符、制表符
 * @param str
 * @returns {void | string | *}
 */
function trim(str) {
  if (str.length === 0) {
    return str;
  }
  str += '';
  // 清除字符串两端空格,包含换行符、制表符
  return str.replace(/(^[\s\n\t]+|[\s\n\t]+$)/g, '');
}

base64数据转blob数据

/**
 * base64数据转blob数据
 * @param base64数据
 * @returns {Blob}
 */
function base64ToBlob(base64) {
  var type = base64.split(",")[0].match(/:(.*?);/)[1];//提取base64头的type如 'image/png'
  var bytes = window.atob(base64.split(',')[1]);//去掉url的头,并转换为byte (atob:编码 btoa:解码)

  //处理异常,将ascii码小于0的转换为大于0
  var ab = new ArrayBuffer(bytes.length);//通用的、固定长度(bytes.length)的原始二进制数据缓冲区对象
  var ia = new Uint8Array(ab);
  for (var i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], { type: type });
}

数值格式化

设置数字的整数位长度(从低位往高位截)

/**
 * 设置数字的整数位长度(从低位往高位截)
 * 如:limitInt(12, 3) => 12
 *    limitInt(145678, 3) => 145
 *    limitInt(1456.78, 3) => 145.78
 * @param num
 * @param maxSize
 * @returns {string}
 */
function limitInt(num, maxSize) {
  num = num + "";
  let numArr = num.split(".");
  let len = (numArr[0] + "").length;
  if (len > maxSize) {
    numArr[0] = numArr[0].substring(0, maxSize);
  } else {
    return num;
  }
  return numArr.join(".");
}

设置小数的最大小数位

/**
 * 设置小数的最大小数位
 * 如:limeDecimal(12, 3) => 12
 *    limeDecimal(14.5678, 3) => 14.557
 *    limeDecimal(1456.78, 3) => 1456.78
 * @param num
 * @param maxSize
 * @returns {string}
 */
function limitDecimal(num, maxSize) {
  if (typeof maxSize == "undefined") {
    return num;
  }
  num = num + "";

  let numArr = num.split(".");
  if (numArr.length == 1) {
    // console.log('limitDecimal', numArr, numArr.join("."))
    return num;
  }
  if ((numArr[1] + "").length > maxSize) {
    numArr[1] = numArr[1].substr(0, maxSize);
  } else {
    // console.log('limitDecimal', numArr, numArr.join("."))
    return num;
  }
  // console.log('limitDecimal', numArr, numArr.join("."))
  return numArr.join(".");
}

给数字前面补零

/**
* 给数字前面补零
* 如:padStartZero(10) => 10
*    padStartZero(5) => 05
* @param num
* @returns {string}
*/
function padStartZero(num) {
  return ('00' + num).substr((num + '').length);
}

将科学计数法的值转换成正常数字

/**
 * 将科学计数法的值转换成正常数字
 * @param num
 * @returns {string}
 */
function toNonExponential(num) {
  var m = num.toExponential().match(/\d(?:\.(\d*))?e([+-]\d+)/);
  return num.toFixed(Math.max(0, (m[1] || '').length - m[2]));
}