跟着月影学 JavaScript(三)| 青训营笔记

65 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5天

前言

上次记录到js的组件封装,这次继续上次的课程内容记录。

高阶函数

以函数作为参数,以函数作为返回值,常用于作为 函数装饰器

常用高阶函数

Once 只执行一次,前文讲过,这里不再阐述

Throttle 节流

为函数添加一个间隔time,每隔time事件调用一次函数,节省其需求,比如某个事件很容易持续的发生(如鼠标移上去就触发),那么他会一直速度特别快的调用这个事件函数,这个时候为其加一个节流函数则可以防止崩溃节约流量。

function throttle(fn, time = 500) {
    let timer;
    return function(...args) {
        if(timer == null) {
            fn.apply(this, args);
            timer = setTimeout(() => {
                timer = null;
            }, timer);
        }
    }
}

btn.onclick = throttle(function(e){
    /* 事件处理 */
    circle.innerHTML = parseInt(circle.innerHTML)+1;
    circle.className = 'fade';
    setTimeout(() => circle.className = '', 250);
});

//输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

对原始的函数进行包装,没有timer的话就注册一个timer,500ms后取消,因为在这500ms中这个timer都还存在,所以不会去执行函数(或者说执行空函数),500ms后timer取消了,函数就可以被调用执行了。

Debounce 防抖

在上面的节流中,timer存在期间是不会去执行函数,而防抖是在每次事件一开始的时候清空timer,然后设置timer为dur,当事件调用dur时间并且没有新的事件再次调用时(比如鼠标移动后悬停一段时间),函数就可以被调用执行了。

function debounce(fn, dur) {
    dur = dur || 100;   // dur若不存在则设置dur为100ms
    var timer;
    return function() {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, arguments);
        }, dur);
    }
}
1
2
3
4
5
6
7
8
9
10

Consumer

这是将一个函数变成类似setTimeout这样的异步操作的函数,如调用了很多次某事件,将这些事件丢到一个列表中,按设定好的时间隔一段时间并执行返回其结果。先来看代码:

function consumer(fn, time) {
    let tasks = [],
        timer;
    return function (...args) {
        tasks.push(fn.bind(this, ...args));
        if(timer == null) {
            timer = setInterval(() => {
                tasks.shift().call(this);
                if(tasks.length <= 0) {
                    clearInterval(timer);
                    timer = null;
                }
            }, time);
        }
    }
}
btn.onclick = consumer((evt) => {
    /*
     * 事件处理 如每次调用了很多次某事件,将这些事件丢到
     * 一个列表中,按设定好的时间隔一段时间并执行返回其结果。 
     */
    let t = parseInt(count.innerHTML.slice(1)) + 1;
    count.className = 'hit';
    let r = t * 7 % 256,
        g = t * 17  % 128,
        b = t * 31  % 128;
    count.style.color = `rgb(${r}, ${g}, ${b})`.trim();
    setTimeout(() => {
        count.className = 'hide';
    }, 500);
}, 800);

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

这里的事件处理实现了点击按钮时执行这个不断显示+count并在500ms后渐隐,而快速点击时,则将这个点击事件存储到是事件列表中每隔800ms执行(不然上一个+count还未消失)。

Iterative

将一个函数,变成可迭代使用的的,这通常用于一个函数要给一组对象执行批量操作的时候。如批量设置颜色,代码如下:

const isIterable = obj => obj != null && typeof obj[Symbol.iterator] === 'function';
function iterative(fn) {
    return function(subject, ...rest) {
        if(isIterable(subject)) {
            const ret = [];
            for(let obj of subject) {
                ret.push(fn.apply(this, [obj, ...rest]));
            }
            return ret;
        }
        return fn.apply(this, [subject, ...rest]);
    }
}
const setColor = iterative((el, color) => {
    el.style.color = color;
})
const els = document.querySelectorAll('li:nth-child(2n+1)');
setColor(els, 'red');

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

总结

这次的记录主要是对课程内容做一个记录,不做特别多的解释了,因为这些网上都有很好的文章了。