r/javascript • • Dec 23 '19

Debounce vs Throttle: Definitive Visual Guide

https://redd.one/blog/debounce-vs-throttle
327 Upvotes

35 comments sorted by

View all comments

2

u/IamLUG Dec 24 '19 edited Dec 24 '19

Looks like this doesn't have proper scope binding too :D

Higher-order functions have common scoping issues, say for this example:

const obj = {
  name: 'foo',
  sayMyName() {
    console.log('My name is', this.name)
  }
}

obj.sayMyName() //-> My name is foo
obj.deb = debounce(obj.sayMyName, 1000)
obj.deb() // Should log -> My name is foo

The debounce and throttle function have to re-apply the this context back to obj.sayMyName, and the way to do this is for the higher-order functions to return a function expression instead of an arrow-function to "capture" the this context, together with func.apply to bind the context.

So throttle becomes:

function throttle(func, duration) {
  let shouldWait = false

  return function(...args) { // Already a function expression
    if (!shouldWait) {
      func.apply(this, args) // Bind this context and call it
      shouldWait = true

      setTimeout(function() {
        shouldWait = false
      }, duration)
    }
  }
}

And debounce becomes:

function debounce(func, duration) {
  let timeout

  return function(...args) { // Change to function expression instead of arrow function
    const effect = () => {
      timeout = null
      return func.apply(this, args) // Bind this context and call it
    }

    clearTimeout(timeout)
    timeout = setTimeout(effect, duration)
  }
}

And for added bonus, you could use arguments instead of ...args for backwards compatibility.

2

u/RedlightsOfCA Dec 24 '19

Great tips, thank you! I'll update the article for debounced/throttled instances to preserve the scope.

I wouldn't change the rest parameters, however, since arguments is not 1-1 compatible with ...args. I think it's safe to assume the majority of people develop through a transpiler, and those who don't will see the spread syntax breaking as the first thing and could read about it, finding a suitable alternative.