关于时间的处理

1. 时间格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* @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;
}

调用示例:

1
2
3
4
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. 获取某年中,某月最后一天是几号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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();
}
}

调用示例:

1
getMonthEnd(2021, 4); // 30

3. 获取某月的总天数

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

调用示例:

1
getMonthDaysCount(2021, 2); // 28

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @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;
}

调用示例:

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

5. 获取上一个月份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 获取上一个月
*
* @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;
}

调用示例:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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. 比较两个日期的大小

1
2
3
4
5
6
7
8
9
10
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 月日期

1
2
3
4
5
6
7
8
9
10
11
12
13
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. 时间日期格式转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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 格式化

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

2. 提取汉字

1
2
3
4
5
6
7
function GetChinese(strValue) {
if (strValue !== null && strValue !== "") {
const reg = /[\u4e00-\u9fa5]/g;
return strValue.match(reg).join("");
}
return "";
}

3. 提取英文

1
2
3
4
5
6
7
function GetaZ(str) {
if (str !== null && str !== "") {
const reg = /[a-zA-Z]/g;
return str.match(reg).join("");
}
return "";
}

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

1
2
3
4
5
6
7
function lrTrim(val) {
if (val === undefined) {
return val;
}
const value = val + "";
return vallue.replace(/(^\s*)|(\s*$)/g, "");
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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, "");
}

调用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//* 去除字符串首尾全部空白*/
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. 获取字节长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @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 <= 0x7ff) s++;
else if (code > 0x7ff && code <= 0xffff) s += 2;
if (code >= 0xdc00 && code <= 0xdfff) i--;
}
return s;
}

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

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

数字格式化

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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,
"$&,"
);
}
}

调用示例:

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

2. 千分号去掉逗号

1
2
3
function delNumFormat(snum) {
return snum.replace(/,/g, "");
}

调用示例:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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. 生成随机数范围

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

关于地图方面

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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. 各种地图坐标系的转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//定义一些常量
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);
}

页面跳转传参 获取参数值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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

1
2
3
4
5
6
7
8
9
10
11
12
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;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//浮点数相加,解决小数运算出现多位小数
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))
);
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
}

数组去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//*利用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
}

数组排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 快排 [left] + min + [right]
function quickArr(arr) {
if (arr.length <= 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] <= 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;
}

去除对象中为空的属性

1
2
3
4
5
6
7
8
function handleValue(data) {
for (var key in data) {
if (data[key] === "" || data[key] === undefined) {
delete data[key];
}
}
return data;
}

递归深拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 递归实现深拷贝 (为了解决循环引用和相同引用、不同类型的深拷贝)
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 参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 "";
}
}

阻止事件冒泡

1
2
3
4
5
6
7
8
9
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;
}
}

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

1
2
3
4
5
6
7
用法示例: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: []}]
}
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* 将一级的数据结构处理成树状数据结构
* @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;
};

获取浏览器类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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;
}
}

跨浏览器删除事件

1
2
3
4
5
6
7
8
9
10
11
12
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 方式下载文件流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//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 链接是否有效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}
}
}

随机数时间戳

1
2
3
4
5
6
7
function uniqueId() {
var a = Math.random,
b = parseInt;
return (
Number(new Date()).toString() + b(10 * a()) + b(10 * a()) + b(10 * a())
);
}

UTF8 解码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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("");
}

获取其数据类型

1
2
3
function type(para) {
return Object.prototype.toString.call(para);
}

字符串去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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");
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 级父元素

1
2
3
4
5
6
7
function parents(ele, n) {
while (ele && n) {
ele = ele.parentElement ? ele.parentElement : ele.parentNode;
n--;
}
return ele;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
}

判断元素有没有子元素

1
2
3
4
5
6
7
8
9
10
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;
}

获得滚动条的滚动距离

1
2
3
4
5
6
7
8
9
10
11
12
13
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,
};
}
}

获得视口的尺寸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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,
};
}
}
}

绑定事件的兼容

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}
}

解绑事件

1
2
3
4
5
6
7
8
9
10
11
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;
}
}

检验字符串是否是回文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
}

运动函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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);
}

弹性运动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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) <= 1 && Math.abs(a) <= 1) {
console.log("over");
clearInterval(obj.timer);
obj.style.left = target + "px";
} else {
obj.style.left = obj.offsetLeft + iSpeed + "px";
}
}, 30);
}

forEach 封装

1
2
3
4
5
6
7
8
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 封装

1
2
3
4
5
6
7
8
9
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 封装

1
2
3
4
5
6
7
8
9
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 封装

1
2
3
4
5
6
7
8
9
10
11
12
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 封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 树

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

原生封装 ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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 封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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() 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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() 实现

1
2
3
4
5
6
7
8
9
10
11
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() 实现

1
2
3
4
5
6
7
8
9
10
11
12
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;
};

防抖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 防抖函数
* @param {*} func
* @param {*} wait
*/
export 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);
}
}
}

节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 节流函数
* @param {*} func
* @param {*} interval
*/
export 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 <= 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)
}
}
}
}

函数柯里化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
function curryIt(fn) {
var length = fn.length,
args = [];
var result = function (arg) {
args.push(arg);
length--;
if (length <= 0) {
return fn.apply(this, args);
} else {
return result;
}
};
return result;
}

html 过滤代码

1
2
3
4
5
6
7
8
const filterTag = function (str) {
// 过滤html代码(把<>转换)
str = str.replace(/&/gi, "&");
str = str.replace(/</gi, "<");
str = str.replace(/>/gi, ">");
str = str.replace(" ", " ");
return str;
};

常用正则验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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;
}
};

文本复制功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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("复制成功");
};

对象序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 图片下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
};

判断图片加载完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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();
}
};
}
};

小数位限制

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

非空判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 非空判断,空对象 {} 、空数组 [] 都为false
* @param {*} data
* @return {boolean}
*/
export 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;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @description 将枚举类型转换为数组格式
* @param {object} data
* @param {Function} callback
* @param {boolean} hasAll 是否添加所有
* @returns {array}
*/
export 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @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();
}
});
}

判断一个值得数据类型

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

判断文件类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* @description: 判断文件类型
* @param {String} filePath
* @return {*}
*/
export 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';
}

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