js一些实用的工具函数

2020/12/21 工具函数

🌙 一些实用的工具函数

🌙 1.数组对象按key去重

export function uniqueArrObjByKey<T>(arr: T[], key?: keyof T): T[] {
    if (!key) {
        return Array.from(new Set(arr));
    }

    const res: T[] = [];
    for (let i = 0; i < arr.length; i++) {
        const has = res.some(d => d[key] === arr[i][key]);
        if (!has) {
            res.push(arr[i]);
        }
    }

    return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

🌙 3.计算滚动条尺寸

function getScrollbarSize() {
    const scrollDiv = document.createElement("div");
    scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;opacity:0';
    document.body.appendChild(scrollDiv);
    // 垂直滚动条宽度
    const x = scrollDiv.offsetWidth - scrollDiv.clientWidth;
    // 水平滚动条宽度
    const y = scrollDiv.offsetHeight - scrollDiv.clientHeight;
    document.body.removeChild(scrollDiv);
    return {xWidth: x, yWidth: y};
}
1
2
3
4
5
6
7
8
9
10
11

🌙 4.判断容器是否出现滚动条

  • 判断body元素:
function hasScrollbar() {
    return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight);
}
1
2
3
  • 判断任意元素:
function hasScrollbar(el: HTMLElement, isVertical = true) {
    if (isVertical) {
        return el.scrollHeight > el.clientHeight;
    } else {
        return el.scrollWidth > el.clientWidth;
    }
}
1
2
3
4
5
6
7

查看Demo (opens new window)

🌙 5.判断各种浏览器版本

// 获取各种浏览器和版本
function getBrowserVersion() {
    const userAgent = navigator.userAgent;
    let info = '';
    let tempArray = [];
    //判断是否Opera浏览器
    const isOpera = userAgent.indexOf('Opera') > -1;
    //判断是否IE浏览器
    const isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 && !isOpera;
    //判断是否IE的Edge浏览器
    const isEdge = userAgent.toLowerCase().indexOf('edge') > -1 && !isIE;
    const isIE11 = userAgent.toLowerCase().indexOf('trident') > -1 && userAgent.indexOf('rv') > -1;

    if (/[Ff]irefox(\/\d+\.\d+)/.test(userAgent)) {
        tempArray = /([Ff]irefox)\/(\d+\.\d+)/.exec(userAgent) || [];
        info += tempArray[1] + tempArray[2];
    } else if (isIE) {
        let version: string;
        let reIE = new RegExp('MSIE (\\d+\\.\\d+);');
        reIE.test(userAgent);
        let fIEVersion = parseFloat(RegExp['$1']);
        if (fIEVersion === 7) {
            version = 'IE7';
        } else if (fIEVersion === 8) {
            version = 'IE8';
        } else if (fIEVersion === 9) {
            version = 'IE9';
        } else if (fIEVersion === 10) {
            version = 'IE10';
        } else {
            version = '0';
        }
        info += version;
    } else if (isEdge) {
        info += 'Edge';
    } else if (isIE11) {
        info += 'IE11';
    } else if (/[Cc]hrome\/\d+/.test(userAgent)) {
        tempArray = /([Cc]hrome)\/(\d+)/.exec(userAgent) || [];
        info += tempArray[1] || '' + tempArray[2] || '';
    } else if (/[Vv]ersion\/\d+\.\d+\.\d+(\.\d)* *[Ss]afari/.test(userAgent)) {
        tempArray = /[Vv]ersion\/(\d+\.\d+\.\d+)(\.\d)* *([Ss]afari)/.exec(userAgent) || [];
        info += tempArray[3] || '' + tempArray[1] || '';
    } else if (/[Oo]pera.+[Vv]ersion\/\d+\.\d+/.test(userAgent)) {
        tempArray = /([Oo]pera).+[Vv]ersion\/(\d+)\.\d+/.exec(userAgent) || [];
        info += tempArray[1] || '' + tempArray[2] || '';
    } else {
        info += 'unknown';
    }
    return info;
}
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

🌙 6.判断指定元素是否在视口可见

/**
 *@param selector: css元素选择器
 *@param partial: 是否部分可见
 */
const isDomVisible = (selector: string, partial = false) => {
        const dom = document.querySelector(selector);
        const {top, left, bottom, right} = dom.getBoundingClientRect();
        const {innerHeight, innerWidth} = window;
        return partial ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
    };

// Examples 
isDomVisible('.img'); // (不完全可见) 
isDomVisible('.img', true); // (部分可见)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

🌙 7.延迟调用函数

const delayFn = (fn: Function, wait = 100, ...args) => setTimeout(fn, wait, ...args); 
1

🌙 8.睡眠等待函数

const sleep = (wait = 100) => new Promise((resolve) => setTimeout(resolve, wait));

// 使用
async function test() {
    await sleep(1000);
    console.log(1111);
}

// 延迟1s输出了1111
test();
1
2
3
4
5
6
7
8
9
10

🌙 9.判断浏览器选项卡是否处于前台活跃状态

const isBrowserTabFocused = () => !document.hidden;

// Example 
isBrowserTabFocused(); // true
1
2
3
4

🌙 10.格式化日期

要求:对于date = new Date('2020-9-8 14:39:09'),格式化说明如下:

字符串 说明
yyyy 年份,2020
yy 年份,20
MM 月份,补满两位,09
M 月份,9
dd 日期,补满两位,08
d 日期,8
HH 24小时制,补满两位,14
H 24小时制,14
hh 12小时制,补满两位,02
h 12小时制,2
mm 分钟,补满两位39
m 分钟,39
ss 秒,补满两位,09
s 秒,9
w 星期,为 ['日', '一', '二', '三', '四', '五', '六'] 中的某一个,本次结果:二
/**
 *@param date: Date日期
 *@param str: 格式化字符串 'YYYY-MM-DD HH:mm:ss 星期w'
 */
function formatDate(date: Date, str = 'YYYY-MM-DD HH:mm:ss 星期w') {
    const obj: { [key: string]: string | number } = {
        YYYY: date.getFullYear(),
        YY: ('' + date.getFullYear()).slice(-2),
        M: date.getMonth() + 1,
        MM: ('0' + (date.getMonth() + 1)).slice(-2),
        D: date.getDate(),
        DD: ('0' + date.getDate()).slice(-2),
        H: date.getHours(),
        HH: ('0' + date.getHours()).slice(-2),
        h: date.getHours() % 12,
        hh: ('0' + (date.getHours() % 12)).slice(-2),
        m: date.getMinutes(),
        mm: ('0' + date.getMinutes()).slice(-2),
        s: date.getSeconds(),
        ss: ('0' + date.getSeconds()).slice(-2),
        w: ['日', '一', '二', '三', '四', '五', '六'][date.getDay()],
    };
    return str.replace(/([a-z]+)/gi, $1 => obj[$1].toString());
}

// "2020-09-08 14:39:09 星期二"
formatDate(new Date('2020-9-8 14:39:09'), 'YYYY-MM-DD HH:mm:ss 星期w')

// "2020-09-08 2:39:09 星期二"
formatDate(new Date('2020-9-8 14:39:09'), 'YYYY-MM-DD h:mm:ss 星期w')

// "09-08 二"
formatDate(new Date('2020-9-8 14:39:09'), 'MM-DD w')

// "2020/09/08 二"
formatDate(new Date('2020/9/8 14:39:09'), 'YYYY/MM/DD w')
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