Understanding of anti – shake function – step by step

The principle of anti – shake and throttling will not be described in detail here, mainly about how to optimize from a simple anti – shake function to a more perfect state. (The final version is slightly better than the current version of online blogs.)

🌟, of course, also provides a link to the principle, which was also my original reference for anti-shock and throttling

My understanding of anti – shake and throttling is: Anti – shake is stopped before the execution, throttling is a fixed time no matter how many times the execution of a fixed number of times

First give a basic version of the anti-shake (not immediately executed)

HTML:

<div id="content"
     style="height:150px; line-height:150px; text-align:center; color: #fff; background-color:lightseagreen; font-size:80px;">
    0
</div>
Copy the code

1. The basic version

js:

let easyDebounce=(func,wait) = >{
    let timeout;
    return function (){
        clearTimeout(timeout);
        timeout=setTimeout(() = >{
            func();
        },wait)
    }
}

let item=document.querySelector("#content");
let num=0;
function count() {
    item.innerHTML = String(++num);
}
item.addEventListener('mousemove',easyDebounce(count,1000));
Copy the code

No matter how many times the div is moved, only the last func is triggered

You can see that we’ve got the basic anti-shake. But there are two drawbacks

  1. We call func() directly, so we can’t pass the count callback, or even the default event, because the event argument is bound to an anonymous function!!
  2. The this of our timer callback refers to the top-level object window, but should have been item!!

(useless talk a few words, bosses can skip 😅 😅 😅 : because it is returned by the function will be binding on the item, the full wording is EventTarget. The addEventListener (). Speak a little more easyDebounce execution time of this point to the window, because the binding on the item of functions not easyBounce but esayBounce return…). The specific implementation is as follows:

let easyDebounce=(func,wait) = >{
    let timeout;
    console.log(this)            / / ▼ window
    return function (){
        console.log(this);         / / ▼ item
        clearTimeout(timeout);
        timeout=setTimeout(() = >{
            func();                
        },wait)
    }
}

let item=document.querySelector("#content");
let num=0;
function count() {
    item.innerHTML = String(++num);
    console.log(this);             / / ▼ window
}
Copy the code

So how to improve?

2. Standard anti-shake

let easyDebounce=(func,wait) = >{
    let timeout;
    return function (){
        let context=this;
        let args=arguments;
        clearTimeout(timeout);

        timeout=setTimeout(() = >{
            func.apply(context,args);
        },wait)
    }
}

let item=document.querySelector("#content");
let num=0;
function count(event) {
    console.log(this);      //item
    console.log(event);     //MouseEvent
    item.innerHTML = String(++num);
}
item.addEventListener('mousemove',easyDebounce(count,1000));
Copy the code

🌟 At this time, we successfully solved the problem of this and parameter passing through apply method!! This is also a popular way to write it

But what if we want to pass a callback to count?

item.addEventListener('mousemove',easyDebounce(count(param),1000));
Copy the code

❌ is not an option. The callback function passes the address to someone else and calls count immediately

To do this, use the following method —— to pass parameters through an external function

3. If Plus

★ Update arguments to REST

const debounce = function (func, wait,... rest) {
    let timeout;
    return function () {
        let context = this;
        let args = rest.concat([...arguments]);
        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(() = > {
            func.apply(context, args);
        }, wait)
    }
}
function count() {
    console.log(this);
    console.log(arguments);  //Arguments(2)['externalArgs',MouseEvent]
    item.innerHTML = String(++num);
}
item.addEventListener('mousemove',debounce(count,1000.'externalArgs'));
Copy the code

We can pass arguments in debounce and use arguments in count

Thank you for reading!! Beginner front-end small white, if there is wrong, please don’t hesitate to give advice!!