Skip to content

前端常用公共方法工具类

这里主要整理了一些常用的前端工具类方法,后续会继续添加......

关于时间的处理

1. 时间格式化

javascript
/**
 * @param {(Object|string|number)} time
 * @param {string} TimeFormat   想要返回时间的格式 例如 '{y}-{m}-{d} {h}:{i}:{s} {a}' {a}为周
 * @returns {string}
 */
function parseTime(time, TimeFormat) {
  if (!time) {
    return null;
  }
  if (arguments.length === 0) {
    return null;
  }
  const format = TimeFormat || "{y}-{m}-{d} {h}:{i}:{s}";
  let date;
  if (typeof time === "object") {
    date = time;
  } else {
    if (typeof time === "string" && /^[0-9]+$/.test(time)) {
      time = parseInt(time);
    }
    if (typeof time === "number" && time.toString().length === 10) {
      time = time * 1000;
    }
    date = new Date(time);
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay(),
  };
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key];
    if (key === "a") {
      return ["日", "一", "二", "三", "四", "五", "六"][value];
    }
    if (result.length > 0 && value < 10) {
      value = "0" + value;
    }
    return value || 0;
  });
  return time_str;
}

调用示例:

javascript
parseTime("1617680226605"); //不填写返回格式 默认为'{y}-{m}-{d} {h}:{i}:{s}' 2021-04-06 11:37:06
parseTime("1617680226605", "{y}-{m}-{d} {h}:{i}:{s}"); //填写对应格式  2021-04-06 11:37:06
parseTime("1617680226605", "{m}-{d}-{y} {h}:{i}:{s}"); //修改格式  04-06-2021 11:37:06
parseTime("1617680226605", "{y}-{m}-{d} {h}:{i}:{s} 周{a}"); //加上周  2021-04-06 11:37:06 周四

2. 获取某年中,某月最后一天是几号

javascript
function getMonthEnd(year, month) {
  month = parseInt(month);
  if (month == 12) {
    var expect = 1;
    year++;
    return new Date(
      new Date(year + "/" + expect + "/1").getTime() - 24 * 60 * 60 * 100
    ).getDate();
  } else {
    return new Date(
      new Date(year + "/" + (month + 1) + "/1").getTime() - 24 * 60 * 60 * 100
    ).getDate();
  }
}

调用示例:

javascript
getMonthEnd(2021, 4); // 30

3. 获取某月的总天数

javascript
function getMonthDaysCount(year, month) {
  return new Date(year, month, 0).getDate();
}

调用示例:

javascript
getMonthDaysCount(2021, 2); // 28

4. 根据起始日期和结束日期计算天数

javascript
/**
 * @param {(Object|string|number)} startDate
 * @param {(Object|string|number)} endDate
 * @returns {string}
 */
function DateDiff(startDate, endDate) {
  var oDate1, oDate2, iDays;
  oDate1 = new Date(
    startDate.substring(4, 6) +
      "-" +
      startDate.substring(6) +
      "-" +
      startDate.substring(0, 4)
  );
  oDate2 = new Date(
    endDate.substring(4, 6) +
      "-" +
      endDate.substring(6) +
      "-" +
      endDate.substring(0, 4)
  );
  iDays = parseInt(Math.abs(oDate1 - oDate2) / 1000 / 60 / 60 / 24);
  return iDays;
}

调用示例:

javascript
DateDiff("2021 03 01", "2021 04 06"); // 37

5. 获取上一个月份

javascript
/**
 * 获取上一个月
 *
 * @date 格式为yyyy-mm-dd的日期,如:2021-04-06
 */
function getPreMonth(date) {
  var arr = date.split("-");
  var year = arr[0]; //获取当前日期的年份
  var month = arr[1]; //获取当前日期的月份
  var day = arr[2]; //获取当前日期的日
  var days = new Date(year, month, 0);
  days = days.getDate(); //获取当前日期中月的天数
  var year2 = year;
  var month2 = parseInt(month) - 1;
  if (month2 == 0) {
    year2 = parseInt(year2) - 1;
    month2 = 12;
  }
  var day2 = day;
  var days2 = new Date(year2, month2, 0);
  days2 = days2.getDate();
  if (day2 > days2) {
    day2 = days2;
  }
  if (month2 < 10) {
    month2 = "0" + month2;
  }
  var t2 = year2 + "-" + month2;
  t2 = day2 ? t2 + "-" + day2 : t2;
  return t2;
}

调用示例:

javascript
getPreMonth("2021-04-06"); // "2021-03-01"

6. 中国标准时间转换成 datetime 格式

javascript
function formatData(time, format) {
  var t = new Date(time);
  var tf = function (i) {
    return (i < 10 ? "0" : "") + i;
  };
  return format.replace(/yyyy|MM|dd|HH|mm|ss/g, function (a) {
    switch (a) {
      case "yyyy":
        return tf(t.getFullYear());
        break;
      case "MM":
        return tf(t.getMonth() + 1);
        break;
      case "mm":
        return tf(t.getMinutes());
        break;
      case "dd":
        return tf(t.getDate());
        break;
      case "HH":
        return tf(t.getHours());
        break;
      case "ss":
        return tf(t.getSeconds());
        break;
    }
  });
}

7. 比较两个日期的大小

javascript
function compareDate(date1, date2) {
  var oDate1 = new Date(date1);
  var oDate2 = new Date(date2);

  if (oDate1.getTime() > oDate2.getTime()) {
    return 1;
  } else {
    return 0;
  }
}

8. 获取前 n 月日期和后 n 月日期

javascript
countMonths(2); //+代表过去  -代表将来
function countMonths(month) {
  var today = new Date();
  var defaultmonth = new Date();
  defaultmonth.setMonth(today.getMonth() - month); //用于设置月份
  var strYear = defaultmonth.getFullYear();
  var strMonth = defaultmonth.getMonth() + 1;
  if (strMonth < 10) {
    strMonth = "0" + strMonth;
  }

  alert(strYear + "-" + strMonth);
}

9. 时间日期格式转换

javascript
Date.prototype.format = function (formatStr) {
  var str = formatStr;
  var Week = ["日", "一", "二", "三", "四", "五", "六"];
  str = str.replace(/yyyy|YYYY/, this.getFullYear());
  str = str.replace(
    /yy|YY/,
    this.getYear() % 100 > 9
      ? (this.getYear() % 100).toString()
      : "0" + (this.getYear() % 100)
  );
  str = str.replace(
    /MM/,
    this.getMonth() + 1 > 9
      ? (this.getMonth() + 1).toString()
      : "0" + (this.getMonth() + 1)
  );
  str = str.replace(/M/g, this.getMonth() + 1);
  str = str.replace(/w|W/g, Week[this.getDay()]);
  str = str.replace(
    /dd|DD/,
    this.getDate() > 9 ? this.getDate().toString() : "0" + this.getDate()
  );
  str = str.replace(/d|D/g, this.getDate());
  str = str.replace(
    /hh|HH/,
    this.getHours() > 9 ? this.getHours().toString() : "0" + this.getHours()
  );
  str = str.replace(/h|H/g, this.getHours());
  str = str.replace(
    /mm/,
    this.getMinutes() > 9
      ? this.getMinutes().toString()
      : "0" + this.getMinutes()
  );
  str = str.replace(/m/g, this.getMinutes());
  str = str.replace(
    /ss|SS/,
    this.getSeconds() > 9
      ? this.getSeconds().toString()
      : "0" + this.getSeconds()
  );
  str = str.replace(/s|S/g, this.getSeconds());
  return str;
};

// 或
Date.prototype.format = function (format) {
  var o = {
    "M+": this.getMonth() + 1, //month
    "d+": this.getDate(), //day
    "h+": this.getHours(), //hour
    "m+": this.getMinutes(), //minute
    "s+": this.getSeconds(), //second
    "q+": Math.floor((this.getMonth() + 3) / 3), //quarter
    S: this.getMilliseconds(), //millisecond
  };
  if (/(y+)/.test(format))
    format = format.replace(
      RegExp.$1,
      (this.getFullYear() + "").substr(4 - RegExp.$1.length)
    );
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(format))
      format = format.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
      );
  }
  return format;
};
alert(new Date().format("yyyy-MM-dd hh:mm:ss"));

字符串处理

1. 将字符串用 js 按大写字母拆分,然后以下划线_拼接并转换成小写返回;用作 table 排序 prop 格式化

javascript
function strsplit(str) {
  let strProp = str.split(/(?=[A-Z])/);
  return strProp.join("_").toLowerCase();
}

2. 提取汉字

javascript
function GetChinese(strValue) {
  if (strValue !== null && strValue !== "") {
    const reg = /[\u4e00-\u9fa5]/g;
    return strValue.match(reg).join("");
  }
  return "";
}

3. 提取英文

javascript
function GetaZ(str) {
  if (str !== null && str !== "") {
    const reg = /[a-zA-Z]/g;
    return str.match(reg).join("");
  }
  return "";
}

4. 去除字符左右两边空格

javascript
function lrTrim(val) {
  if (val === undefined) {
    return val;
  }
  const value = val + "";
  return vallue.replace(/(^\s*)|(\s*$)/g, "");
}

5. 去除字符两头空格或者指定字符

javascript
function trim(char, type) {
  if (char) {
    if (type == "left") {
      return this.replace(new RegExp("^\\" + char + "+", "g"), "");
    } else if (type == "right") {
      return this.replace(new RegExp("\\" + char + "+$", "g"), "");
    }
    return this.replace(
      new RegExp("^\\" + char + "+|\\" + char + "+$", "g"),
      ""
    );
  }
  return this.replace(/^\s+|\s+$/g, "");
}

调用示例:

javascript
//* 去除字符串首尾全部空白*/
var str = "  Imagine  ";
console.log("aaa" + str.trim() + "bbb"); // aaaImaginebbb

//* 去除字符串左侧空白*/
str = "  Imagine  ";
console.log("aaa" + str.trim(" ", "left") + "bbb"); // aaaImagine  bbb

//* 去除字符串右侧字符*/
str = "  Imagine  ";
console.log("aaa" + str.trim(" ", "right") + "bbb"); // aaa  Imaginebbb

//* 去除字符串两侧指定字符*/
str = "/Imagine/";
console.log(str.trim("?")); // Imagine

//* 去除字符串左侧指定字符*/
str = "?Imagine/";
console.log(str.trim("?", "left")); // Imagine/

//* 去除字符串右侧指定字符*/
str = "?Imagine/";
console.log(str.trim("/", "right")); // ?Imagine

6. 获取字节长度

javascript
/**
 * @param {String} str
 * @returns {Number}
 */
function byteLength(str) {
  let s = str.length;
  for (var i = str.length - 1; i >= 0; i--) {
    const code = str.charCodeAt(i);
    if (code > 0x7f && code &lt;= 0x7ff) s++;
    else if (code > 0x7ff && code &lt;= 0xffff) s += 2;
    if (code >= 0xdc00 && code &lt;= 0xdfff) i--;
  }
  return s;
}

7. 判断是否以某个字符串结束

javascript
String.prototype.endWith = function (s) {
  var d = this.length - s.length;
  return d >= 0 && this.lastIndexOf(s) == d;
};

数字格式化

1. 千分号加逗号,即个位数开始每隔三位数,就用逗号隔开

javascript
function numFormat(num) {
  if (num == null) {
    return;
  }
  if (!isNaN(num)) {
    num = num.toString();
  }
  if (num.indexOf(".") != -1) {
    var decimals = num.split(".")[1];
    return (
      (parseInt(Number(num)) + "").replace(
        /\d{1,3}(?=(\d{3})+(\.\d*)?$)/g,
        "$&,"
      ) +
      "." +
      decimals.substring(0, 2)
    );
  } else {
    return (parseInt(Number(num)).toFixed(0) + "").replace(
      /\d{1,3}(?=(\d{3})+(\.\d*)?$)/g,
      "$&,"
    );
  }
}

调用示例:

javascript
numFormat(10000000.08); // 10,000,000.08

2. 千分号去掉逗号

javascript
function delNumFormat(snum) {
  return snum.replace(/,/g, "");
}

调用示例:

javascript
delNumFormat("10,100,100,100.08"); // 10100100100.08

3. 阿拉伯数字转中文大写数字

javascript
const numberToChinese = function (num) {
  // 将阿拉伯数字翻译成中文的大写数字
  let AA = new Array(
    "零",
    "一",
    "二",
    "三",
    "四",
    "五",
    "六",
    "七",
    "八",
    "九",
    "十"
  );
  let BB = new Array("", "十", "百", "仟", "萬", "億", "点", "");
  let a = ("" + num).replace(/(^0*)/g, "").split(".");
  let k = 0;
  let re = "";
  for (let i = a[0].length - 1; i >= 0; i--) {
    switch (k) {
      case 0:
        re = BB[7] + re;
        break;
      case 4:
        if (!new RegExp("0{4}//d{" + (a[0].length - i - 1) + "}$").test(a[0])) {
          re = BB[4] + re;
        }
        break;
      case 8:
        re = BB[5] + re;
        BB[7] = BB[5];
        k = 0;
        break;
    }
    if (k % 4 === 2 && a[0].charAt(i + 2) !== 0 && a[0].charAt(i + 1) === 0) {
      re = AA[0] + re;
    }
    if (a[0].charAt(i) !== 0) {
      re = AA[a[0].charAt(i)] + BB[k % 4] + re;
    }
    k++;
  }
  if (a.length > 1) {
    // 加上小数部分(如果有小数部分)
    re += BB[6];
    for (let i = 0; i < a[1].length; i++) {
      re += AA[a[1].charAt(i)];
    }
  }
  if (re === "一十") {
    re = "十";
  }
  if (re.match(/^/) && re.length === 3) {
    re = re.replace("一", "");
  }
  return re;
};

4. 生成随机数范围

javascript
const random = function (min, max) {
  // 生成随机数范围
  if (arguments.length === 2) {
    return Math.floor(min + Math.random() * (max + 1 - min));
  } else {
    return null;
  }
};

关于地图方面

1. 计算两个经纬度之间的距离

javascript
function distance(la1, lo1, la2, lo2) {
  var La1 = (la1 * Math.PI) / 180.0;
  var La2 = (la2 * Math.PI) / 180.0;
  var La3 = La1 - La2;
  var Lb3 = (lo1 * Math.PI) / 180.0 - (lo2 * Math.PI) / 180.0;
  var s =
    2 *
    Math.asin(
      Math.sqrt(
        Math.pow(Math.sin(La3 / 2), 2) +
          Math.cos(La1) * Math.cos(La2) * Math.pow(Math.sin(Lb3 / 2), 2)
      )
    );
  s = s * 6378.137;
  s = Math.round(s * 10000) / 10000;
  s = s * 1000; //转为米单位
  s = s.toFixed(2);
  return s;
}

2. 各种地图坐标系的转换

javascript
//定义一些常量
var x_PI = (3.14159265358979324 * 3000.0) / 180.0;
var PI = 3.1415926535897932384626;
var a = 6378245.0;
var ee = 0.00669342162296594323;

/**
 * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
 * 即 百度 转 谷歌、高德
 * @param bd_lon
 * @param bd_lat
 * @returns {*[]}
 */
function bd09togcj02(bd_lon, bd_lat) {
  var bd_lon = +bd_lon;
  var bd_lat = +bd_lat;
  var x = bd_lon - 0.0065;
  var y = bd_lat - 0.006;
  var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
  var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
  var gg_lng = z * Math.cos(theta);
  var gg_lat = z * Math.sin(theta);
  return [gg_lng, gg_lat];
}

/**
 * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
 * 即谷歌、高德 转 百度
 * @param lng
 * @param lat
 * @returns {*[]}
 */
function gcj02tobd09(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
  var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
  var bd_lng = z * Math.cos(theta) + 0.0065;
  var bd_lat = z * Math.sin(theta) + 0.006;
  return [bd_lng, bd_lat];
}

/**
 * WGS84转GCj02
 * @param lng
 * @param lat
 * @returns {*[]}
 */
function wgs84togcj02(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  if (out_of_china(lng, lat)) {
    return [lng, lat];
  } else {
    var dlat = transformlat(lng - 105.0, lat - 35.0);
    var dlng = transformlng(lng - 105.0, lat - 35.0);
    var radlat = (lat / 180.0) * PI;
    var magic = Math.sin(radlat);
    magic = 1 - ee * magic * magic;
    var sqrtmagic = Math.sqrt(magic);
    dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
    dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
    var mglat = lat + dlat;
    var mglng = lng + dlng;
    return [mglng, mglat];
  }
}

/**
 * GCJ02 转换为 WGS84
 * @param lng
 * @param lat
 * @returns {*[]}
 */
function gcj02towgs84(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  if (out_of_china(lng, lat)) {
    return [lng, lat];
  } else {
    var dlat = transformlat(lng - 105.0, lat - 35.0);
    var dlng = transformlng(lng - 105.0, lat - 35.0);
    var radlat = (lat / 180.0) * PI;
    var magic = Math.sin(radlat);
    magic = 1 - ee * magic * magic;
    var sqrtmagic = Math.sqrt(magic);
    dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
    dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
    var mglat = lat + dlat;
    var mglng = lng + dlng;
    return [lng * 2 - mglng, lat * 2 - mglat];
  }
}

function transformlat(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  var ret =
    -100.0 +
    2.0 * lng +
    3.0 * lat +
    0.2 * lat * lat +
    0.1 * lng * lat +
    0.2 * Math.sqrt(Math.abs(lng));
  ret +=
    ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
      2.0) /
    3.0;
  ret +=
    ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) /
    3.0;
  ret +=
    ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) *
      2.0) /
    3.0;
  return ret;
}

function transformlng(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  var ret =
    300.0 +
    lng +
    2.0 * lat +
    0.1 * lng * lng +
    0.1 * lng * lat +
    0.1 * Math.sqrt(Math.abs(lng));
  ret +=
    ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
      2.0) /
    3.0;
  ret +=
    ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) /
    3.0;
  ret +=
    ((150.0 * Math.sin((lng / 12.0) * PI) +
      300.0 * Math.sin((lng / 30.0) * PI)) *
      2.0) /
    3.0;
  return ret;
}

/**
 * 判断是否在国内,不在国内则不做偏移
 * @param lng
 * @param lat
 * @returns {boolean}
 */
function out_of_china(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  // 纬度3.86~53.55,经度73.66~135.05
  return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
}

页面跳转传参 获取参数值

javascript
function getUrlParam(name) {
  var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
  var r = decodeURIComponent(window.location.search).substr(1).match(reg);
  if (r != null) return unescape(r[2]);
  return null;
}

/**提取url地址中的参数
 * @param {String} url
 * @returns {Object}
 */
function getQueryObject(url) {
  url = url == null ? window.location.href : url;
  const search = url.substring(url.lastIndexOf("?") + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}

//*获取url连接问号后面的参数*/
function queryValue(query) {
  var url = window.location.href.split("?")[1];
  var arr = url.split("&");
  if (arr && arr.length > 0) {
    for (var i = 0; i < arr.length; i++) {
      var queryVal = arr[i].split("=");
      if (queryVal[0] == query) return queryVal[1];
    }
  }
}

前端获取 uuid

javascript
getUuid() {
   var d = new Date().getTime();
   if (window.performance && typeof window.performance.now === "function") {
        d += performance.now();  //use high-precision timer if available
   }
   var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
       var r = (d + Math.random() * 16) % 16 | 0;
       d = Math.floor(d / 16);
       return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
   });
  return uuid;
}

两个数的加减乘除,解决小数运算出现多位小数

javascript
//浮点数相加,解决小数运算出现多位小数
function addNum(num1, num2) {
  var sq1, sq2, m;
  try {
    sq1 = num1.toString().split(".")[1].length;
  } catch (e) {
    sq1 = 0;
  }
  try {
    sq2 = num2.toString().split(".")[1].length;
  } catch (e) {
    sq2 = 0;
  }
  m = Math.pow(10, Math.max(sq1, sq2));
  return (num1 * m + num2 * m) / m;
}

//浮点数相减,解决小数运算出现多位小数
function subNum(num1, num2) {
  var r1, r2, m, n;
  try {
    r1 = num1.toString().split(".")[1].length;
  } catch (e) {
    r1 = 0;
  }
  try {
    r2 = num2.toString().split(".")[1].length;
  } catch (e) {
    r2 = 0;
  }
  m = Math.pow(10, Math.max(r1, r2));
  n = r1 >= r2 ? r1 : r2;
  return (Math.round(num1 * m - num2 * m) / m).toFixed(n);
}

//浮点数相乘,解决小数运算出现多位小数
function mulNum(num1, num2) {
  var m = 0,
    r1,
    r2;
  var s1 = num1.toString();
  var s2 = num2.toString();
  try {
    m += s1.split(".")[1].length;
  } catch (e) {}
  try {
    m += s2.split(".")[1].length;
  } catch (e) {}
  r1 = Number(num1.toString().replace(".", ""));
  r2 = Number(num2.toString().replace(".", ""));
  return (r1 * r2) / Math.pow(10, m);
}

//浮点数相除,解决小数运算出现多位小数
function divNum(num1, num2) {
  var c,
    d,
    e = 0,
    f = 0;
  try {
    e = num1.toString().split(".")[1].length;
  } catch (g) {}
  try {
    f = num2.toString().split(".")[1].length;
  } catch (g) {}
  return (
    (c = Number(num1.toString().replace(".", ""))),
    (d = Number(num2.toString().replace(".", ""))),
    this.mulNum(c / d, Math.pow(10, f - e))
  );
}

判断是否为空对象、空数组

javascript
function isEmpty(obj) {
  //检验 null 和 undefined 和 ''
  if (!obj && obj !== 0) {
    return true;
  }
  //检验数组
  if (Array.prototype.isPrototypeOf(obj) && obj.length === 0) {
    return true;
  }
  //检验对象
  if (Object.prototype.isPrototypeOf(obj) && Object.keys(obj).length === 0) {
    return true;
  }
  return false;
}

数组去重

javascript
//*利用ES6 Set去重*/
/**
 * @param {Array} arr
 * @returns {Array}
 */
function uniqueArr(arr) {
    if (!Array.isArray(arr)) {
      console.log('请传入数组')
      return
    }
    return Array.from(new Set(arr))
};

//* 根据对象的属性不同去重 */
handleRepeatArr({data, key}) {
    if (!Array.isArray(data)) {
      console.log('请传入数组')
      return
    }
    let arr = [], obj = {}
    data.forEach((item, index) => {
      let attr = key ? item[key] : item
      if (!obj[attr]) {
        obj[attr] = index + 1
        arr.push(item)
      }
    })
    return arr
};

//* 利用indexOf以及forEach (适合处理数组,不适合处理对象数组)*/
handleRepeatArr({data, key}) {
    if (!Array.isArray(data)) {
      console.log('请传入数组')
      return
    }
    let arr = []
    data.forEach((item, index) => {
      // 如果当前元素在之后没有出现过(后面出现的数据会保留)
      // let result = data.indexOf(item, index + 1)
      // 如果当前元素在之前没有出现过(前面出现的数据会保留)
      let result = index === 0 ? -1 : data.lastIndexOf(item, index - 1)
      if (result === -1) {
        arr.push(item)
      }
    })
    return arr
};

//* 双层循环去重 (占用内存高)*/
handleRepeatArr ({data, key}) {
    if (!Array.isArray(data)) {
      console.log('请传入数组')
      return
    }
    for (let i = 0, len = data.length; i < len; i++) {
      for (let j = i + 1; j < len; j++) {
        let result = key ? data[i][key] === data[j][key] : data[i] === data[j]
        if (result) {
          data.splice(j, 1)
          len--
          j--
        }
      }
    }
    return data
};

//* 递归去重(数据无法保持之前的排序)*/
handleRepeatArr ({data, key}) {
    if (!Array.isArray(data)) {
      console.log('请传入数组')
      return
    }
    // 先对数据做排序处理
    data = data.sort((item, item1) => {
      if (key) {
        return item[key] - item1[key]
      }
      return item - item1
    })
    // 递归去重
    function getData (index) {
      if (index >= 1) {
        // 判断当前数据和下一条数据是否相等
        let result = key ? data[index][key] === data[index - 1][key] : data[index] === data[index - 1]
        if (result) {
          data.splice(index, 1)
        }
        getData(index - 1)
      }
    }
    getData(data.length - 1)
    return data
}

数组排序

javascript
// 快排 [left] + min + [right]
function quickArr(arr) {
  if (arr.length &lt;= 1) {
    return arr;
  }
  var left = [],
    right = [];
  var pIndex = Math.floor(arr.length / 2);
  var p = arr.splice(pIndex, 1)[0];
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] &lt;= p) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  // 递归
  return quickArr(left).concat([p], quickArr(right));
}

// 冒泡
function bubbleSort(arr) {
  for (var i = 0; i < arr.length - 1; i++) {
    for (var j = i + 1; j < arr.length; j++) {
      if (arr[i] > arr[j]) {
        var temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
      }
    }
  }
  return arr;
}

function bubbleSort(arr) {
  var len = arr.length;
  for (var i = 0; i < len - 1; i++) {
    for (var j = 0; j < len - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        var temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
  return arr;
}

去除对象中为空的属性

javascript
function handleValue(data) {
  for (var key in data) {
    if (data[key] === "" || data[key] === undefined) {
      delete data[key];
    }
  }
  return data;
}

递归深拷贝

javascript
// 递归实现深拷贝 (为了解决循环引用和相同引用、不同类型的深拷贝)
function isObject(obj) {
  // 判断类型
  return obj !== null && typeof obj === "object";
}
/**通过闭包维护一个变量,变量中储存已经遍历过的对象
 *每次递归时判断当前的参数是否已经存在于变量中,如果已经存在,就说明已经递归过该变量,就可以停止这次递归并返回上次递归该变量时的返回值
 */
function _deepClone(obj) {
  let visitedObjs = [];
  function baseClone(target) {
    if (!isObject(target)) return target;
    for (let i = 0; i < visitedObjs.length; i++) {
      if (visitedObjs[i].target === target) {
        return visitedObjs[i].result;
      }
    }
    let result = Array.isArray(target) ? [] : {};
    visitedObjs.push({ target, result });
    const keys = Object.keys(target);
    for (let i = 0, len = keys.length; i < len; i++) {
      result[keys[i]] = baseClone(target[keys[i]]);
    }
    return result;
  }
  return baseClone(obj);
}

json 转 url 参数

javascript
function parseParams(data) {
  try {
    var tempArr = [];
    for (var i in data) {
      var key = encodeURIComponent(i);
      var value = encodeURIComponent(data[i]);
      tempArr.push(key + "=" + value);
    }
    var urlParamsStr = tempArr.join("&");
    return urlParamsStr;
  } catch (err) {
    return "";
  }
}

阻止事件冒泡

javascript
function stopEventPropagation() {
  if (event.stopPropagation) {
    // this code is for Mozilla and Opera
    event.stopPropagation();
  } else if (window.event) {
    // this code is for IE
    window.event.cancelBubble = true;
  }
}

将有层级关系的列表转换成树状数据

用法示例:let arr = [{id: 1, pid: 0, name: '一级'}, {id: 2, pid: 1, name: '二级'}],
           arr1 = getTreeArr({key: 'id', pKey: 'pid', rootPValue: 0, data: arr})
得到的数据为:
       arr1 = [
           {id: 1, pid: 0, name: '一级', children: [{id: 2, pid: 1, name: '二级', children: []}]
           }
       ]
javascript
/**
 * 将一级的数据结构处理成树状数据结构
 * @param {Object} obj {key, pKey, data}
 *  @param obj.key  字段名称 比如id
 *  @param obj.pKey 父字段名称 比如 pid
 *  @param obj.rootPValue 根节点的父字段的值
 *  @param obj.data 需要处理的数据
 * @return {Array} arr
 */
getTreeArr: (obj) => {
  if (!Array.isArray(obj.data)) {
    console.log("getTreeArr=>请传入数组");
    return [];
  }
  let arr = obj.data,
    arr1 = [];
  // 将数据处理成数状结构
  arr.forEach((item) => {
    let index = 0;
    item.children = [];
    arr.forEach((item1) => {
      // 得到树结构关系
      if (item[obj.key] === item1[obj.pKey]) {
        item.children.push(item1);
      }
      // 判断根节点
      if (item1.id !== item.pid) {
        index++;
      }
      // 传入根节点,根据传入的根节点组成树结构
      if (rootPValue in obj && item[obj.pKey] === obj.rootPValue) {
        arr1.push(item);
      }
    });
    // 没传入根节点,根据当前数据结构得到根节点
    if (!(rootPValue in obj) && index === arr.length) {
      arr1.push(item);
    }
  });
  return arr1;
};

获取浏览器类型

javascript
function getBrowserType() {
  let str = window.navigator.userAgent;
  let name;
  if (str.indexOf("Opera") > -1 || str.indexOf("OPR") > -1) {
    name = "Opera";
    return name;
  }
  if (str.indexOf("Edge") > -1) {
    name = "Edge";
    return name;
  }
  if (str.indexOf("Firefox") > -1) {
    name = "Firefox";
    return name;
  }
  if (str.indexOf("Chrome") > -1 && str.indexOf("Safari") > -1) {
    name = "Chrome";
    return name;
  }
  if (str.indexOf("Chrome") === -1 && str.indexOf("Safari") > -1) {
    name = "Safari";
    return name;
  }
  if (
    (str.indexOf("Opera") === -1 && str.indexOf("MSIE") > -1) ||
    str.indexOf("Trident") > -1
  ) {
    name = "IE";
    return name;
  }
}

跨浏览器删除事件

javascript
function delEvt(obj, evt, fn) {
  if (!obj) {
    return;
  }
  if (obj.addEventListener) {
    obj.addEventListener(evt, fn, false);
  } else if (oTarget.attachEvent) {
    obj.attachEvent("on" + evt, fn);
  } else {
    obj["on" + evt] = fn;
  }
}

post 方式下载文件流

javascript
//ajax post 获取流,下载file文件
function downloadFilePostStream(apiStr, option) {
  //option为 传给后台的参数
  let body = document.body || document.getElementsByTagName("body")[0];
  let form = document.createElement("form");
  form.className = "myDownloadForm";
  form.setAttribute("action", `${globalHost}${apiStr}`); //配置
  form.setAttribute("method", "post");
  form.setAttribute("name", "downloadForm");
  form.setAttribute("target", "_blank");
  for (let key in option) {
    if (option[key] !== undefined && option[key] !== null) {
      //form表单的形式传undefined 会被转成字符串'undefined',干脆直接不传了
      let input = document.createElement("input");
      input.setAttribute("name", key);
      input.value = option[key];
      form.appendChild(input);
    }
  }
  body.appendChild(form);
  form.submit();
  setTimeout(() => {
    body.removeChild(form);
  }, 50);
}

检验 URL 链接是否有效

javascript
function getUrlState(URL) {
  var xmlhttp = new ActiveXObject("microsoft.xmlhttp");
  xmlhttp.Open("GET", URL, false);
  try {
    xmlhttp.Send();
  } catch (e) {
  } finally {
    var result = xmlhttp.responseText;
    if (result) {
      if (xmlhttp.Status == 200) {
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }
}

随机数时间戳

javascript
function uniqueId() {
  var a = Math.random,
    b = parseInt;
  return (
    Number(new Date()).toString() + b(10 * a()) + b(10 * a()) + b(10 * a())
  );
}

UTF8 解码

javascript
function utf8_decode(str_data) {
  var tmp_arr = [],
    i = 0,
    ac = 0,
    c1 = 0,
    c2 = 0,
    c3 = 0;
  str_data += "";
  while (i < str_data.length) {
    c1 = str_data.charCodeAt(i);
    if (c1 < 128) {
      tmp_arr[ac++] = String.fromCharCode(c1);
      i++;
    } else if (c1 > 191 && c1 < 224) {
      c2 = str_data.charCodeAt(i + 1);
      tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
      i += 2;
    } else {
      c2 = str_data.charCodeAt(i + 1);
      c3 = str_data.charCodeAt(i + 2);
      tmp_arr[ac++] = String.fromCharCode(
        ((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)
      );
      i += 3;
    }
  }
  return tmp_arr.join("");
}

获取其数据类型

javascript
function type(para) {
  return Object.prototype.toString.call(para);
}

字符串去重

javascript
String.prototype.unique = function () {
  var obj = {},
    str = "",
    len = this.length;
  for (var i = 0; i < len; i++) {
    if (!obj[this[i]]) {
      str += this[i];
      obj[this[i]] = true;
    }
  }
  return str;
};

//去除连续的字符串
function uniq(str) {
  return str.replace(/(\w)\1+/g, "$1");
}

找出字符串中第一次只出现一次的字母

javascript
String.prototype.firstAppear = function () {
  var obj = {},
    len = this.length;
  for (var i = 0; i < len; i++) {
    if (obj[this[i]]) {
      obj[this[i]]++;
    } else {
      obj[this[i]] = 1;
    }
  }
  for (var prop in obj) {
    if (obj[prop] == 1) {
      return prop;
    }
  }
};

找元素的第 n 级父元素

javascript
function parents(ele, n) {
  while (ele && n) {
    ele = ele.parentElement ? ele.parentElement : ele.parentNode;
    n--;
  }
  return ele;
}

返回元素的第 n 个兄弟节点

javascript
function retSibling(e, n) {
  while (e && n) {
    if (n > 0) {
      if (e.nextElementSibling) {
        e = e.nextElementSibling;
      } else {
        for (e = e.nextSibling; e && e.nodeType !== 1; e = e.nextSibling);
      }
      n--;
    } else {
      if (e.previousElementSibling) {
        e = e.previousElementSibling;
      } else {
        for (
          e = e.previousElementSibling;
          e && e.nodeType !== 1;
          e = e.previousElementSibling
        );
      }
      n++;
    }
  }
  return e;
}

判断元素有没有子元素

javascript
function hasChildren(e) {
  var children = e.childNodes,
    len = children.length;
  for (var i = 0; i < len; i++) {
    if (children[i].nodeType === 1) {
      return true;
    }
  }
  return false;
}

获得滚动条的滚动距离

javascript
function getScrollOffset() {
  if (window.pageXOffset) {
    return {
      x: window.pageXOffset,
      y: window.pageYOffset,
    };
  } else {
    return {
      x: document.body.scrollLeft + document.documentElement.scrollLeft,
      y: document.body.scrollTop + document.documentElement.scrollTop,
    };
  }
}

获得视口的尺寸

javascript
function getViewportOffset() {
  if (window.innerWidth) {
    return {
      w: window.innerWidth,
      h: window.innerHeight,
    };
  } else {
    // ie8及其以下
    if (document.compatMode === "BackCompat") {
      // 怪异模式
      return {
        w: document.body.clientWidth,
        h: document.body.clientHeight,
      };
    } else {
      // 标准模式
      return {
        w: document.documentElement.clientWidth,
        h: document.documentElement.clientHeight,
      };
    }
  }
}

绑定事件的兼容

javascript
function addEvent(elem, type, handle) {
  if (elem.addEventListener) {
    //非ie和非ie9
    elem.addEventListener(type, handle, false);
  } else if (elem.attachEvent) {
    //ie6到ie8
    elem.attachEvent("on" + type, function () {
      handle.call(elem);
    });
  } else {
    elem["on" + type] = handle;
  }
}

解绑事件

javascript
function removeEvent(elem, type, handle) {
  if (elem.removeEventListener) {
    //非ie和非ie9
    elem.removeEventListener(type, handle, false);
  } else if (elem.detachEvent) {
    //ie6到ie8
    elem.detachEvent("on" + type, handle);
  } else {
    elem["on" + type] = null;
  }
}

检验字符串是否是回文

javascript
function isPalindrome(str) {
    str = str.replace(/\W/g, '').toLowerCase();
    console.log(str)
    return (str == str.split('').reverse().join(''))
}

===========

function isPalina(str) {
    if (Object.prototype.toString.call(str) !== '[object String]') {
        return false;
    }
    var len = str.length;
    for (var i = 0; i < len / 2; i++) {
        if (str[i] != str[len - 1 - i]) {
            return false;
        }
    }
    return true;
}

运动函数

javascript
function animate(obj, json, callback) {
  clearInterval(obj.timer);
  var speed, current;
  obj.timer = setInterval(function () {
    var lock = true;
    for (var prop in json) {
      if (prop == "opacity") {
        current = parseFloat(window.getComputedStyle(obj, null)[prop]) * 100;
      } else {
        current = parseInt(window.getComputedStyle(obj, null)[prop]);
      }
      speed = (json[prop] - current) / 7;
      speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

      if (prop == "opacity") {
        obj.style[prop] = (current + speed) / 100;
      } else {
        obj.style[prop] = current + speed + "px";
      }
      if (current != json[prop]) {
        lock = false;
      }
    }
    if (lock) {
      clearInterval(obj.timer);
      typeof callback == "function" ? callback() : "";
    }
  }, 30);
}

弹性运动

javascript
function ElasticMovement(obj, target) {
  clearInterval(obj.timer);
  var iSpeed = 40,
    a,
    u = 0.8;
  obj.timer = setInterval(function () {
    a = (target - obj.offsetLeft) / 8;
    iSpeed = iSpeed + a;
    iSpeed = iSpeed * u;
    if (Math.abs(iSpeed) &lt;= 1 && Math.abs(a) &lt;= 1) {
      console.log("over");
      clearInterval(obj.timer);
      obj.style.left = target + "px";
    } else {
      obj.style.left = obj.offsetLeft + iSpeed + "px";
    }
  }, 30);
}

forEach 封装

javascript
Array.prototype.myForEach = function (func, obj) {
  var len = this.length;
  var _this = arguments[1] ? arguments[1] : window;
  // var _this=arguments[1]||window;
  for (var i = 0; i < len; i++) {
    func.call(_this, this[i], i, this);
  }
};

filter 封装

javascript
Array.prototype.myFilter = function (func, obj) {
  var len = this.length;
  var arr = [];
  var _this = arguments[1] || window;
  for (var i = 0; i < len; i++) {
    func.call(_this, this[i], i, this) && arr.push(this[i]);
  }
  return arr;
};

map 封装

javascript
Array.prototype.myMap = function (func) {
  var arr = [];
  var len = this.length;
  var _this = arguments[1] || window;
  for (var i = 0; i < len; i++) {
    arr.push(func.call(_this, this[i], i, this));
  }
  return arr;
};

every 封装

javascript
Array.prototype.myEvery = function (func) {
  var flag = true;
  var len = this.length;
  var _this = arguments[1] || window;
  for (var i = 0; i < len; i++) {
    if (func.apply(_this, [this[i], i, this]) == false) {
      flag = false;
      break;
    }
  }
  return flag;
};

reduce 封装

javascript
Array.prototype.myReduce = function (func, initialValue) {
  var len = this.length,
    nextValue,
    i;
  if (!initialValue) {
    // 没有传第二个参数
    nextValue = this[0];
    i = 1;
  } else {
    // 传了第二个参数
    nextValue = initialValue;
    i = 0;
  }
  for (; i < len; i++) {
    nextValue = func(nextValue, this[i], i, this);
  }
  return nextValue;
};

遍历 DOM 树

javascript
// 给定页面上的DOM元素,将访问元素本身及其所有后代(不仅仅是它的直接子元素)
// 对于每个访问的元素,函数讲元素传递给提供的回调函数
function traverse(element, callback) {
  callback(element);
  var list = element.children;
  for (var i = 0; i < list.length; i++) {
    traverse(list[i], callback);
  }
}

原生封装 ajax

javascript
const ajax = function (conf) {
  // ajax操作
  let url = conf.url,
    data = conf.data,
    senData = [], // 封装后的数据
    async = conf.async !== undefined ? conf.async : true, // ture为异步请求
    type = conf.type || "get", // 默认请求方式get
    dataType = conf.dataType || "json",
    contenType = conf.contenType || "application/x-www-form-urlencoded",
    success = conf.success,
    error = conf.error,
    isForm = conf.isForm || false, // 是否formdata
    header = conf.header || {}, // 头部信息
    xhr = ""; // 创建ajax引擎对象
  if (data == null) {
    senData = "";
  } else if (typeof data === "object" && !isForm) {
    // 如果data是对象,转换为字符串
    for (var k in data) {
      senData.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k]));
    }
    senData = senData.join("&");
  } else {
    senData = data;
  }
  try {
    xhr = new ActiveXObject("microsoft.xmlhttp"); // IE内核系列浏览器
  } catch (e1) {
    try {
      xhr = new XMLHttpRequest(); // 非IE内核浏览器
    } catch (e2) {
      if (error != null) {
        error("不支持ajax请求");
      }
    }
  }
  xhr.open(type, type !== "get" ? url : url + "?" + senData, async);
  if (type !== "get" && !isForm) {
    xhr.setRequestHeader("content-type", contenType);
  }
  for (var h in header) {
    xhr.setRequestHeader(h, header[h]);
  }
  xhr.send(type !== "get" ? senData : null);
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        if (dataType === "json" && success != null) {
          let res = "";
          try {
            res = eval("(" + xhr.responseText + ")");
          } catch (e) {
            console.log(e);
          }
          success(res); // 将json字符串转换为js对象
        }
      } else {
        if (error != null) {
          error("通讯失败!" + xhr.status);
        }
      }
    }
  };
};

fetch 封装

javascript
const fetch = function (url, setting) {
  // fetch请求的封装
  let opts = {
    // 设置参数的初始值
    method: (setting.method || "GET").toUpperCase(), // 请求方式
    headers: setting.headers || {}, // 请求头设置
    credentials: setting.credentials || true, // 设置cookie是否一起发送
    body: setting.body || {},
    mode: setting.mode || "no-cors", // 可以设置 cors, no-cors, same-origin
    redirect: setting.redirect || "follow", // follow, error, manual
    cache: setting.cache || "default", // 设置 cache 模式 (default, reload, no-cache)
  };
  let dataType = setting.dataType || "json"; // 解析方式
  let data = setting.data || ""; // 参数
  let paramsFormat = function (obj) {
    // 参数格式
    var str = "";
    for (var i in obj) {
      str += `${i}=${obj[i]}&`;
    }
    return str.split("").slice(0, -1).join("");
  };

  if (opts.method === "GET") {
    url = url + (data ? `?${paramsFormat(data)}` : "");
  } else {
    setting.body = data || {};
  }
  return new Promise((resolve, reject) => {
    fetch(url, opts)
      .then(async (res) => {
        let data =
          dataType === "text"
            ? await res.text()
            : dataType === "blob"
            ? await res.blob()
            : await res.json();
        resolve(data);
      })
      .catch((e) => {
        reject(e);
      });
  });
};

异步加载 script

javascript
function loadScript(url, callback) {
  var oscript = document.createElement("script");
  if (oscript.readyState) {
    // ie8及以下版本
    oscript.onreadystatechange = function () {
      if (
        oscript.readyState === "complete" ||
        oscript.readyState === "loaded"
      ) {
        callback();
      }
    };
  } else {
    oscript.onload = function () {
      callback();
    };
  }
  oscript.src = url;
  document.body.appendChild(oscript);
}

javascript
var cookie = {
  set: function (name, value, time) {
    document.cookie = name + "=" + value + "; max-age=" + time;
    return this;
  },
  remove: function (name) {
    return this.setCookie(name, "", -1);
  },
  get: function (name, callback) {
    var allCookieArr = document.cookie.split("; ");
    for (var i = 0; i < allCookieArr.length; i++) {
      var itemCookieArr = allCookieArr[i].split("=");
      if (itemCookieArr[0] === name) {
        return itemCookieArr[1];
      }
    }
    return undefined;
  },
};

bind() 实现

javascript
Function.prototype.myBind = function (target) {
  var target = target || window;
  var _args1 = [].slice.call(arguments, 1);
  var self = this;
  var temp = function () {};
  var F = function () {
    var _args2 = [].slice.call(arguments, 0);
    var parasArr = _args1.concat(_args2);
    return self.apply(this instanceof temp ? this : target, parasArr);
  };
  temp.prototype = self.prototype;
  F.prototype = new temp();
  return F;
};

call() 实现

javascript
Function.prototype.myCall = function () {
  var ctx = arguments[0] || window;
  ctx.fn = this;
  var args = [];
  for (var i = 1; i < arguments.length; i++) {
    args.push(arguments[i]);
  }
  var result = ctx.fn(...args);
  delete ctx.fn;
  return result;
};

apply() 实现

javascript
Function.prototype.myApply = function () {
  var ctx = arguments[0] || window;
  ctx.fn = this;
  if (!arguments[1]) {
    var result = ctx.fn();
    delete ctx.fn;
    return result;
  }
  var result = ctx.fn(...arguments[1]);
  delete ctx.fn;
  return result;
};

防抖

javascript
/**
 * 防抖函数
 * @param {*} func
 * @param {*} wait
 */
function debounce(func, wait = 500) {
  let timeout; // 定时器变量
  return function (event) {
    clearTimeout(timeout); // 每次触发时先清除上一次的定时器,然后重新计时
    event.persist && event.persist(); //保留对事件的引用
    timeout = setTimeout(() => {
      func(event);
    }, wait); // 指定 xx ms 后触发真正想进行的操作 handler
  };
}

============


const debounce = function(func, wait, immediate) {
// 函数防抖[func 函数,wait 延迟执行毫秒数,immediate true 表立即执行,false 表非立即执行,立即执行是触发事件后函数会立即执行,然后n秒内不触发事件才能继续执行函数的效果]
  let timeout;
  return function() {
    let context = this;
    let args = arguments;
    if (timeout) clearTimeout(timeout);
    if (immediate) {
      var callNow = !timeout;
      timeout = setTimeout(() => {
        timeout = null;
      }, wait)
      if (callNow) func.apply(context, args)
    } else {
      timeout = setTimeout(function() {
        func.apply(context, args)
      }, wait);
    }
  }
}

节流

javascript
/**
 * 节流函数
 * @param {*} func
 * @param {*} interval
 */
function throttle(func, interval = 100) {
  let timeout;
  let startTime = new Date();
  return function (event) {
    event.persist && event.persist(); //保留对事件的引用
    clearTimeout(timeout);
    let curTime = new Date();
    if (curTime - startTime &lt;= interval) {
      //小于规定时间间隔时,用setTimeout在指定时间后再执行
      timeout = setTimeout(() => {
        func(event);
      }, interval);
    } else {
      //重新计时并执行函数
      startTime = curTime;
      func(event);
    }
  };
}

=========


const throttle = function(func, wait ,type) { //函数节流 [func 函数 wait 延迟执行毫秒数 type 1 表时间戳版,2 表定时器版]
    if(type === 1){
        let previous = 0;
    }else if(type === 2){
        let timeout;
    }
    return function() {
        let context = this;
        let args = arguments;
        if(type===1){
            let now = Date.now();
            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            }
        }else if(type===2){
            if (!timeout) {
                timeout = setTimeout(() => {
                    timeout = null;
                    func.apply(context, args)
                }, wait)
            }
        }
    }
}

函数柯里化

javascript
//是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
function curryIt(fn) {
  var length = fn.length,
    args = [];
  var result = function (arg) {
    args.push(arg);
    length--;
    if (length &lt;= 0) {
      return fn.apply(this, args);
    } else {
      return result;
    }
  };
  return result;
}

html 过滤代码

javascript
const filterTag = function (str) {
  // 过滤html代码(把<>转换)
  str = str.replace(/&/gi, "&");
  str = str.replace(/&lt;/gi, "<");
  str = str.replace(/&gt;/gi, ">");
  str = str.replace(" ", " ");
  return str;
};

常用正则验证

javascript
const checkStr = function (str, type) {
  // 常用正则验证,注意type大小写
  switch (type) {
    case "phone": // 手机号码
      return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str);
    case "tel": // 座机
      return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
    case "card": // 身份证
      return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
    case "pwd": // 密码以字母开头,长度在6~18之间,只能包含字母、数字和下划线
      return /^[a-zA-Z]\w{5,17}$/.test(str);
    case "postal": // 邮政编码
      return /[1-9]\d{5}(?!\d)/.test(str);
    case "QQ": // QQ号
      return /^[1-9][0-9]{4,9}$/.test(str);
    case "email": // 邮箱
      return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
    case "money": // 金额(小数点2位)
      return /^\d*(?:\.\d{0,2})?$/.test(str);
    case "URL": // 网址
      return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(
        str
      );
    case "IP": // IP
      return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(
        str
      );
    case "date": // 日期时间
      return (
        /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(
          str
        ) || /^(\d{4})\-(\d{2})\-(\d{2})$/.test(str)
      );
    case "number": // 数字
      return /^[0-9]$/.test(str);
    case "english": // 英文
      return /^[a-zA-Z]+$/.test(str);
    case "chinese": // 中文
      return /^[\u4E00-\u9FA5]+$/.test(str);
    case "lower": // 小写
      return /^[a-z]+$/.test(str);
    case "upper": // 大写
      return /^[A-Z]+$/.test(str);
    case "HTML": // HTML标记
      return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
    default:
      return true;
  }
};

文本复制功能

javascript
const copyTxt = function (text, fn) {
  // 复制功能
  if (typeof document.execCommand !== "function") {
    console.log("复制失败,请长按复制");
    return;
  }
  var dom = document.createElement("textarea");
  dom.value = text;
  dom.setAttribute("style", "display: block;width: 1px;height: 1px;");
  document.body.appendChild(dom);
  dom.select();
  var result = document.execCommand("copy");
  document.body.removeChild(dom);
  if (result) {
    console.log("复制成功");
    typeof fn === "function" && fn();
    return;
  }
  if (typeof document.createRange !== "function") {
    console.log("复制失败,请长按复制");
    return;
  }
  var range = document.createRange();
  var div = document.createElement("div");
  div.innerhtml = text;
  div.setAttribute("style", "height: 1px;fontSize: 1px;overflow: hidden;");
  document.body.appendChild(div);
  range.selectNode(div);
  var selection = window.getSelection();
  console.log(selection);
  if (selection.rangeCount > 0) {
    selection.removeAllRanges();
  }
  selection.addRange(range);
  document.execCommand("copy");
  typeof fn === "function" && fn();
  console.log("复制成功");
};

对象序列化

javascript
const stringfyQueryString = function (obj) {
  //对象序列化【对象转url参数】
  if (!obj) return "";
  let pairs = [];
  for (let key in obj) {
    let value = obj[key];
    if (value instanceof Array) {
      for (let i = 0; i < value.length; ++i) {
        pairs.push(
          encodeURIComponent(key + "[" + i + "]") +
            "=" +
            encodeURIComponent(value[i])
        );
      }
      continue;
    }
    pairs.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
  }
  return pairs.join("&");
};

图片地址转 base64

javascript
const getBase64 = function (img) {
  //传入图片路径,返回base64,使用getBase64(url).then(function(base64){},function(err){});
  let getBase64Image = function (img, width, height) {
    //width、height调用时传入具体像素值,控制大小,不传则默认图像大小
    let canvas = document.createElement("canvas");
    canvas.width = width ? width : img.width;
    canvas.height = height ? height : img.height;
    let ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
    let dataURL = canvas.toDataURL();
    return dataURL;
  };
  let image = new Image();
  image.crossOrigin = "";
  image.src = img;
  let deferred = $.Deferred();
  if (img) {
    image.onload = function () {
      deferred.resolve(getBase64Image(image));
    };
    return deferred.promise();
  }
};

base64 图片下载

javascript
const downloadFile = function (base64, fileName) {
  //base64图片下载功能
  let base64ToBlob = function (code) {
    let parts = code.split(";base64,");
    let contentType = parts[0].split(":")[1];
    let raw = window.atob(parts[1]);
    let rawLength = raw.length;
    let uInt8Array = new Uint8Array(rawLength);
    for (let i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], {
      type: contentType,
    });
  };
  let aLink = document.createElement("a");
  let blob = base64ToBlob(base64); //new Blob([content]);
  let evt = document.createEvent("HTMLEvents");
  evt.initEvent("click", true, true); //initEvent不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
  aLink.download = fileName;
  aLink.href = URL.createObjectURL(blob);
  aLink.click();
};

判断图片加载完成

javascript
const imgLoadAll = function (arr, callback) {
  // 图片加载
  let arrImg = [];
  for (let i = 0; i < arr.length; i++) {
    let img = new Image();
    img.src = arr[i];
    img.onload = function () {
      arrImg.push(this);
      if (arrImg.length == arr.length) {
        callback && callback();
      }
    };
  }
};

小数位限制

js
/**
 * @desc 小数位限制,四舍五入,不足不补位,末数为无意义0时去掉
 * @param {Number} value
 * @param {Number} length
 * @return {Number}
 */
function parseFloatToFixed(value, length) {
  const val = Number.isNaN(Number(value)) ? 0 : value;
  const num = 10 ** length;
  return Math.round(val * num) / num;
}

非空判断

js
/**
 * 非空判断,空对象 {} 、空数组 [] 都为false
 * @param {*} data
 * @return {boolean}
 */
function isEmpty(data) {
  if (data instanceof Array) {
    return !data.length;
  }
  if (data instanceof Object) {
    return !Object.keys(data).length;
  }
  if (typeof data === 'string') {
    return !data.trim();
  }
  return !data;
}

将枚举类型转换为数组格式

js
/**
 * @description 将枚举类型转换为数组格式
 * @param {object} data
 * @param {Function} callback
 * @param {boolean} hasAll 是否添加所有
 * @returns {array}
 */
function formatEnumToArray(data, hasAll, callback) {
  if (isEmpty(data)) return [];
  const options = Object.keys(data).map((key) => {
    if (callback && typeof callback === 'function') return callback(key, data[key]);
    return { value: key, name: data[key] };
  });
  if (hasAll) return [...formatEnumToArray(allLabel, false, callback), ...options];
  return options;
}

处理接口返回的response

js
/**
 * @description 处理接口返回的response
 * @param {object} res
 * @returns {Promise}
 */
function checkResponse(res) {
  return new Promise((resolve, reject) => {
    const { success, data, message } = res;
    if (success) {
      resolve(data);
    } else {
      reject();
    }
  });
}

判断一个值得数据类型

js
/**
 * @desc 判断一个值得数据类型
 */
export function type(param) {
  return Object.prototype.toString.call(param).slice(8, -1);
}

判断文件类型

js
/**
 * @description: 判断文件类型
 * @param {String}  filePath
 * @return {*}
 */
function judgeFileType(filePath) {
  // 获取最后一个.的位置
  const index = filePath.lastIndexOf('.');
  // 获取后缀
  const ext = filePath.substr(index + 1);

  // 判断是否是图片类型
  if (
    ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff'].indexOf(
      ext.toLowerCase(),
    ) !== -1
  ) {
    return 'image';
  }

  // 判断是否是视频类型
  if (['mp4', 'avi', 'mov', 'rmvb', 'rm', 'flv', '3gp'].indexOf(ext.toLowerCase()) !== -1) {
    return 'video';
  }

  // 判断是否是音频类型
  if (['cda', 'wav', 'mp3', 'wmv', 'flac', 'aac'].indexOf(ext.toLowerCase()) !== -1) {
    return 'audio';
  }
  return 'otherType';
}

文件导出处理

js
/**
 * @func 处理导出的文件流
 * @param {@} res 请求返回的数据
 */
const handleExportFileStream = (res = {}, fileName) => {
  if (!fileName) {
    // 获取headers中的filename文件名
    if (res.headers['content-disposition']) {
      const tempName = res.headers['content-disposition'].split(';')[1].split('filename=')[1];
      fileName = decodeURI(tempName);
    }
  }
  if (res.data.type.split(';')[0] == 'text/plain') {
    const reader = new FileReader();
    reader.readAsText(res.data);
    reader.onload = () => {
      console.log('reader.result', reader.result);
      MessageBox({ type: 'error', message: JSON.parse(reader.result).mess, title: '提示' });
    };
  } else {
    // ie dege浏览器
    if ('msSaveOrOpenBlob' in navigator) {
      window.navigator.msSaveOrOpenBlob(res.data, fileName);
      return;
    }
    const blobPath = window.URL.createObjectURL(res.data); // 二进制对象转换成url地址
    const link = document.createElement('a');
    link.style.display = 'none';
    link.href = blobPath;
    link.setAttribute('download', fileName);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link); // 下载完成移除元素
    window.URL.revokeObjectURL(blobPath); // 释放掉blob对象
  }
};

获取一个元素的距离文档(document)的位置

js
/**
 * @desc  获取一个元素的距离文档(document)的位置,类似jQ中的offset()
 * @param {HTMLElement} ele
 * @returns { {left: number, top: number} }
 */
function offset(ele) {
  const pos = {
    left: 0,
    top: 0,
  };
  let myEle = ele;
  while (myEle) {
    pos.left += myEle.offsetLeft;
    pos.top += myEle.offsetTop;
    myEle = myEle.offsetParent;
  }
  return pos;
}

更多...:https://mp.weixin.qq.com/s/TheqYyIgi0MjmoYy7Ak6Vg