工具函数
... 2022-3-9 About 5 min
# 工具函数
# 1. isStatic:检测数据是不是除了symbol外的原始数据
let isStatic = value =>
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean' ||
typeof value === 'undefined' ||
typeof value === 'null'
1
2
3
4
5
6
2
3
4
5
6
# 2. isPrimitive:检验数据是不是原始数据
let isPrimitive = value => isStatic(value) || typeof value === 'symbol'
1
# 3.isObject:判断数据是不是引用类型的数据
eg:array、function、object、regexexs、new String()
let isObject = value =>
(value !== null) &&
(typeof value === 'object' || typeof value === 'function')
1
2
3
2
3
# 4. isObjectLike:检查value是否是类对象
let isObjectLike = value => value !== null && typeof value === 'object'
1
# 5. getRawType:获取精确的数据类型
let getRawType = value =>
Object.prototype.toString.call(value).match(/\[object (.*?)\]/)[1].toLowerCase()
1
2
2
# 6. isNative:判断value是不是浏览器的内置函数
let isNative = value =>
typeof value === 'function' &&
/native code/.test(value.toString())
1
2
3
2
3
备注:这个地方不是很准的,比如说let b = function(){return 'native code'}
, b.toString() ---> 'native code'
# 7. isLength:检查value是不是有效的类数组长度
let isLength = value =>
typeof value === 'number' && // 数组长度一定是数字
value > -1 && // 数组长度一定不为负数
value % 1 == 0 && // 数组长度一定是整数
value <= Number.MAX_SAFE_INTEGER // 数组长度肯定小于无穷大
1
2
3
4
5
2
3
4
5
# 8. isArrayLike:检查value是不是类数组
let isArrayLike = value =>
isLength(value.length) && // 长度必须先满足
getRawType(value) !== 'function' // 函数肯定不能当作类数组的,在这里,字符串是当作类数组的
1
2
3
2
3
# 9. isEmpty:检查value是不是为空
let isEmpty = value => {
if (!value) { // 这其中包含String、Number、Boolean、undefined、null
return true
}
if (getRawType(value) === 'array') { // 数组类型的时候
return !value.length
} else if (getRawType(value) === 'obiect') { // 对象类型的时候
return !Object.keys(value).length
}
return false
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 10. camelize:横线转驼峰
const camelizeGeg = /-(\w)/g // 表示-加字母的形式
let camelize = value =>
value.replace(camelizeGeg, (str, c) => c ? c.toUpperCase() : '')
1
2
3
2
3
# 11. hyphenate:驼峰转横线
const hyphenateReg = /\B([A-Z])/g // \B可以理解为任意字符
let hyphenate = value =>
value.replace(hyphenateReg, '-$1').toLowerCase() // $1表示匹配到的大写字母
1
2
3
2
3
# 12. extend:将属性混合到目标对象中
有Object.assign() 这个玩意真的没什么用
let extend = (to,from) => {
for(let [key,value] of Object.entries(from)){
to[key] = value
}
return to
}
1
2
3
4
5
6
2
3
4
5
6
# 13. Object.assign: 对象属性的复制,浅拷贝
Object.assign = Object.assign || function (){
if (arguments.length === 0) {
throw new TypeError('Cannot convert undefined or null to object')
}
let target = arguments[0]
let args = [].slice(arguments)
args.forEach(item => {
for(let [key,value] of Object.entries(item)){
target[key] = value
}
})
return target
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 14. clone:克隆数据,可深度克隆
let clone = (value,deep) => {
if (isPrimitive(value)) { // 如果是原始数据类型,直接返回
return value
}
if (isArrayLike(value)) { // 如果是类数组
value = [].slice.call(value)
return value.map(item => deep ? clone(item,deep) : item)
} else if (getRawType(value) === 'object' || getRawType(value) === 'array') {
let target = {}
for (let key in value) {
value.hasOwnProperty(key) && ( target[key] = deep ? clone(value[key],deep) : value[key])
}
return target
}
let type = getRawType(value)
switch (type) {
case 'date' :
case 'regexp' :
case 'error' :
return new window[type](value)
break
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
思想就是,如果是原始数据类型直接返回值,没有深浅之分,如果是数组和对象类的引用数据类型,遍历的方法返回是深拷贝,还是浅拷贝
# 15. 识别各种浏览器以及平台
//运行环境是浏览器
let inBrowser = typeof window !== 'undefined'
//运行环境是微信
let inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform
let weexPlatform = inWeex && WXEnvironment.platform.toLowerCase()
//浏览器 UA 判断
let UA = inBrowser && window.navigator.userAgent.toLowerCase()
let isIE = UA && /msie|trident/.test(UA)
let isIE9 = UA && UA.indexOf('msie 9.0') > 0
let isEdge = UA && UA.indexOf('edge/') > 0
let isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android')
let isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
let isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge
export default {
inBrowser,
inWeex,
weexPlatform,
UA,
isIE,
isIE9,
isEdge,
isAndroid,
isIOS,
isChrome
}
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
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
# 16. 获取浏览器信息
export default function getExplorerInfo() {
let t = navigator.userAgent.toLowerCase();
return 0 <= t.indexOf("msie") ? { //ie < 11
type: "IE",
version: Number(t.match(/msie ([\d]+)/)[1])
} : !!t.match(/trident\/.+?rv:(([\d.]+))/) ? { // ie 11
type: "IE",
version: 11
} : 0 <= t.indexOf("edge") ? {
type: "Edge",
version: Number(t.match(/edge\/([\d]+)/)[1])
} : 0 <= t.indexOf("firefox") ? {
type: "Firefox",
version: Number(t.match(/firefox\/([\d]+)/)[1])
} : 0 <= t.indexOf("chrome") ? {
type: "Chrome",
version: Number(t.match(/chrome\/([\d]+)/)[1])
} : 0 <= t.indexOf("opera") ? {
type: "Opera",
version: Number(t.match(/opera.([\d]+)/)[1])
} : 0 <= t.indexOf("Safari") ? {
type: "Safari",
version: Number(t.match(/version\/([\d]+)/)[1])
} : {
type: t,
version: -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
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
# 17. isPCBroswer:检测是否为PC端浏览器模式
export default function isPCBroswer() {
let e = navigator.userAgent.toLowerCase()
, t = "ipad" == e.match(/ipad/i)
, i = "iphone" == e.match(/iphone/i)
, r = "midp" == e.match(/midp/i)
, n = "rv:1.2.3.4" == e.match(/rv:1.2.3.4/i)
, a = "ucweb" == e.match(/ucweb/i)
, o = "android" == e.match(/android/i)
, s = "windows ce" == e.match(/windows ce/i)
, l = "windows mobile" == e.match(/windows mobile/i);
return !(t || i || r || n || a || o || s || l)
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 18: 简单的实现Set
window.Set = window.Set || function () {
function Set (arr) {
this.items = arr ? unique(arr) : []
this.size = this.arr.length
}
Set.prototype = {
add: function (value) {
if (!this.has(value)) {
this.items.push(value)
this.size++
}
return this
},
clear:function() {
this.size = 0
this.items = []
},
delete: function (value) {
return this.items.some ((v,i) => {
if (v === value) {
this.items.splice(i,1)
return true
}
return false
})
},
has: function (value) {
return this.items.some(item => item === value)
},
values: function () {
return this.items
}
}
}
function unique(arr) {
if(!isArrayLink(arr)) { //不是类数组对象
return arr
}
let result = []
let objarr = []
let obj = Object.create(null)
arr.forEach(item => {
if(isStatic(item)) { // 是除了symbol外的原始数据
let key = item + '_' + getRawType(item);
if(!obj[key]){
obj[key] = true
result.push(item)
}
} else { // 引用类型及symbol
if(!objarr.includes(item)) {
objarr.push(item)
result.push(item)
}
}
})
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
# 19. cached记忆函数:缓存函数的运算结果
function cached (fn) {
let cache= = Object.create(null)
return function cachedFn (str) {
let hit = cache(str)
let hit || (cache(str) = fn(str))
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 20. 文件下载
export default function downloadFile (filename, data) {
let DownloadLink = document.createElement('a')
if (DownloadLink) {
document.body.appendChild(DownloadLink)
DownloadLink.style = 'display: none'
DownloadLink.download = filename
DownloadLink.href = data
if (document.createEvent) {
let DownloadEvt = document.createEvent('MouseEvents')
DownloadEvt.initEvent('click', true, false)
DownloadLink.dispatchEvent(DownloadEvt)
} else if (document.createEventObject) {
DownloadLink.fireEvent('onclick');
} else if (typeof DownloadLink.onclick == 'function') {
DownloadLink.onclick();
}
document.body.removeChild(DownloadLink)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 21. 全屏展示和退出
function toFullScreen(){
let elem = document.body;
elem.webkitRequestFullScreen
? elem.webkitRequestFullScreen()
: elem.mozRequestFullScreen
? elem.mozRequestFullScreen()
: elem.msRequestFullscreen
? elem.msRequestFullscreen()
: elem.requestFullScreen
? elem.requestFullScreen()
: alert("浏览器不支持全屏");
}
function exitFullscreen(){
let elem = parent.document;
elem.webkitCancelFullScreen
? elem.webkitCancelFullScreen()
: elem.mozCancelFullScreen
? elem.mozCancelFullScreen()
: elem.cancelFullScreen
? elem.cancelFullScreen()
: elem.msExitFullscreen
? elem.msExitFullscreen()
: elem.exitFullscreen
? elem.exitFullscreen()
: alert("切换失败,可尝试Esc退出");
}
export default {
toFullScreen,
exitFullscreen
}
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
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
# 22. performance.timing: 利用performance.timing进行性能分析
window.onload = function(){
setTimeout(function(){
let t = performance.timing
console.log('DNS查询耗时 :' + (t.domainLookupEnd - t.domainLookupStart).toFixed(0))
console.log('TCP链接耗时 :' + (t.connectEnd - t.connectStart).toFixed(0))
console.log('request请求耗时 :' + (t.responseEnd - t.responseStart).toFixed(0))
console.log('解析dom树耗时 :' + (t.domComplete - t.domInteractive).toFixed(0))
console.log('白屏时间 :' + (t.responseStart - t.navigationStart).toFixed(0))
console.log('domready时间 :' + (t.domContentLoadedEventEnd - t.navigationStart).toFixed(0))
console.log('onload时间 :' + (t.loadEventEnd - t.navigationStart).toFixed(0))
if(t = performance.memory){
console.log('js内存使用占比 :' + (t.usedJSHeapSize / t.totalJSHeapSize * 100).toFixed(2) + '%')
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16