有人可以解释Javascript中的“去抖动”功能

有人可以解释Javascript中的“去抖动”功能

我对javascript中的“debouncing”函数很感兴趣,这里写的:http//davidwalsh.name/javascript-debounce-function

不幸的是,代码没有清楚地解释清楚,以便我理解。任何人都可以帮我弄清楚它是如何工作的(我在下面留下了我的评论)。总之,我真的不明白这是如何工作的

   // Returns a function, that, as long as it continues to be invoked, will not
   // be triggered. The function will be called after it stops being called for
   // N milliseconds.function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };};

编辑:复制的代码片段之前有callNow错误的位置。


暮色呼如
浏览 402回答 3
3回答

慕哥9229398

问题中的代码稍微改变了链接中的代码。在链接中,检查是否(immediate && !timeout)在创建新的timout之前。拥有它后立即模式永远不会开火。我已经更新了我的答案,以便从链接中注释工作版本。function debounce(func, wait, immediate) {   // 'private' variable for instance   // The returned function will be able to reference this due to closure.   // Each call to the returned function will share this common timer.   var timeout;   // Calling debounce returns a new anonymous function   return function() {     // reference the context and args for the setTimeout function     var context = this,       args = arguments;     // Should the function be called now? If immediate is true     //   and not already in a timeout then the answer is: Yes     var callNow = immediate && !timeout;     // This is the basic debounce behaviour where you can call this      //   function several times, but it will only execute once      //   [before or after imposing a delay].      //   Each time the returned function is called, the timer starts over.     clearTimeout(timeout);     // Set the new timeout     timeout = setTimeout(function() {       // Inside the timeout function, clear the timeout variable       // which will let the next execution run when in 'immediate' mode       timeout = null;       // Check if the function already ran with the immediate flag       if (!immediate) {         // Call the original function with apply         // apply lets you define the 'this' object as well as the arguments          //    (both captured before setTimeout)         func.apply(context, args);       }     }, wait);     // Immediate mode and no wait timer? Execute the function..     if (callNow) func.apply(context, args);   }}/////////////////////////////////// DEMO:function onMouseMove(e){   console.clear();   console.log(e.x, e.y);}// Define the debounced functionvar debouncedMouseMove = debounce(onMouseMove, 50);// Call the debounced function on every mouse movewindow.addEventListener('mousemove', debouncedMouseMove);

杨魅力

这里要注意的重要一点是debounce产生一个“关闭” 变量的函数timeout。timeout在生成函数的每次调用期间,即使在debounce返回之后,变量仍然可以访问,并且可以在不同的调用之间进行切换。总体思路debounce如下:没有超时开始。如果调用生成的函数,则清除并重置超时。如果超时,请调用原始函数。第一点是var timeout;,它确实是公正的undefined。幸运的是,clearTimeout它的输入相当松散:传递一个undefined计时器标识符会导致它什么也不做,它不会抛出错误或其他东西。第二点由生成的函数完成。它首先在变量中存储有关调用的一些信息(this上下文和arguments),以便稍后可以将它们用于去抖动调用。然后它清除超时(如果有一组),然后创建一个新的替换它使用setTimeout。请注意,这会覆盖timeout多个函数调用的值,并且该值会持续存在!这允许去抖动实际工作:如果多次调用该函数,timeout则使用新的计时器多次覆盖。如果不是这种情况,多次呼叫将导致启动多个定时器,这些定时器都保持活动状态 - 呼叫只会被延迟,但不会被去抖动。第三点是在超时回调中完成的。它取消设置timeout变量并使用存储的调用信息进行实际的函数调用。该immediate标志应该控制是否应该在定时器之前或之后调用该函数。如果是false,则直到计时器被命中后才调用原始函数。如果是true,则首先调用原始函数,并且在计时器被命中之前不再调用它。但是,我确实认为if (immediate && !timeout)检查错误:timeout刚刚设置为返回的计时器标识符,setTimeout因此!timeout始终false在该点,因此永远不能调用该函数。当前版本的underscore.js似乎有一个稍微不同的检查,它immediate && !timeout 在调用之前进行评估setTimeout。(算法也有点不同,例如它不使用clearTimeout。)这就是为什么你应该总是尝试使用最新版本的库。:-)

慕斯709654

去抖动函数在调用时不会执行,它们会在执行前等待一段可配置的持续时间暂停调用; 每次新调用都会重新启动计时器。限制函数执行,然后等待可配置的持续时间,然后再次触发。去抖动非常适合按键事件; 当用户开始输入然后暂停时,您将所有按键提交为单个事件,从而减少处理调用。对于您只希望允许用户在设定的一段时间内调用一次的实时端点,Throttle非常适合。查看Underscore.js的实现。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript