javascript _.debounce 有什么作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15927371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does _.debounce do?
提问by mikemaccana
A project I've been working on uses _.debounce().
我一直在做的一个项目使用 _.debounce()。
The Underscore JS documentation for debouncereads as follows:
debounce
_.debounce(function, wait, [immediate])
Creates and returns a new debounced version of the passed function that will postpone its execution until after waitmilliseconds have elapsed since the last time it was invoked.
去抖动
_.debounce(function, wait, [immediate])
创建并返回传递函数的新去抖动版本,该版本将推迟执行,直到自上次调用以来经过等待毫秒。
This obviously assumes that anyone who wants to know what debounce()
does, already knows what 'debounce' means.
这显然假设任何想知道什么的人debounce()
都已经知道“去抖动”是什么意思。
What does debounce actually do?
去抖实际上是做什么的?
回答by epascarello
Basically it throttles calls so if it is called more than once in a short period of time, only one instance will be called.
基本上它会限制调用,因此如果在短时间内多次调用它,则只会调用一个实例。
Why would you use it?
你为什么要使用它?
Events like window.onresize fire multiple times in rapid succession. If you need to do a lot of calculations on the new position, you would not want to fire the calculations multiple times. You only want to fire it when the user has finished the resizing event.
window.onresize 之类的事件会连续快速触发多次。如果您需要对新头寸进行大量计算,您不会希望多次触发计算。您只想在用户完成调整大小事件时触发它。
回答by HymanPoint
Description from the source codeof underscore.js:
underscore.js源代码说明:
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. If 'immediate' is passed, trigger the function on the leading edge, instead of the trailing.
返回一个函数,只要它继续被调用,就不会被触发。该函数将在停止调用 N 毫秒后被调用。如果传递了“立即”,则在前沿而不是后沿触发该函数。
Code it self:
自己编码:
_.debounce = function(func, wait, immediate) {
var timeout, result;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) result = func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(context, args);
return result;
};
};
回答by John Dugan
I wrote a post titled Demystifying Debounce in JavaScriptwhere I explain exactly how a debounce function worksand include a demo.
我写了一篇题为Demystifying Debounce in JavaScript 的文章,我在其中准确解释了 debounce 函数的工作原理并包括一个演示。
A debounce function provides a way to "throttle" a function's execution. They are typically used in circumstances where a function is bound to an event that fires in rapid succession. It is common to see a debounce function being used on window resizes and scrolls.
去抖动函数提供了一种“限制”函数执行的方法。它们通常用于函数绑定到快速连续触发的事件的情况。经常看到在窗口调整大小和滚动时使用去抖动功能。
Whether Underscores or another JavaScript library, all debounce functions are built on JavaScript's native setTimeout
method. So, before you dive into understanding what a debounce function does, it's a good idea to have a thorough understanding of WindowTimers
(links to MDN).
无论是 Underscores 还是其他 JavaScript 库,所有的 debounce 函数都是建立在 JavaScript 的原生setTimeout
方法之上的。因此,在深入了解去抖动函数的作用之前,最好彻底了解WindowTimers
(链接到 MDN)。
Additionally, you'll want to have a good understanding of scope and closures. Although relatively small in size, debounce functions actually employ some pretty advanced JavaScript concepts!
此外,您需要对作用域和闭包有一个很好的理解。虽然尺寸相对较小,但 debounce 函数实际上使用了一些非常先进的 JavaScript 概念!
With that said, below is the basic debounce function explained and demoed in my post referenced above.
话虽如此,下面是我在上面引用的帖子中解释和演示的基本去抖动功能。
The finished product
成品
// Create JD Object
// ----------------
var JD = {};
// Debounce Method
// ---------------
JD.debounce = function(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 || 200);
if ( callNow ) {
func.apply(context, args);
}
};
};
The explanation
说明
// Create JD Object
// ----------------
/*
It's a good idea to attach helper methods like `debounce` to your own
custom object. That way, you don't pollute the global space by
attaching methods to the `window` object and potentially run in to
conflicts.
*/
var JD = {};
// Debounce Method
// ---------------
/*
Return 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 `wait` milliseconds. If `immediate` is passed, trigger the
function on the leading edge, instead of the trailing.
*/
JD.debounce = function(func, wait, immediate) {
/*
Declare a variable named `timeout` variable that we will later use
to store the *timeout ID returned by the `setTimeout` function.
*When setTimeout is called, it retuns a numeric ID. This unique ID
can be used in conjunction with JavaScript's `clearTimeout` method
to prevent the code passed in the first argument of the `setTimout`
function from being called. Note, this prevention will only occur
if `clearTimeout` is called before the specified number of
milliseconds passed in the second argument of setTimeout have been
met.
*/
var timeout;
/*
Return an anomymous function that has access to the `func`
argument of our `debounce` method through the process of closure.
*/
return function() {
/*
1) Assign `this` to a variable named `context` so that the
`func` argument passed to our `debounce` method can be
called in the proper context.
2) Assign all *arugments passed in the `func` argument of our
`debounce` method to a variable named `args`.
*JavaScript natively makes all arguments passed to a function
accessible inside of the function in an array-like variable
named `arguments`. Assinging `arguments` to `args` combines
all arguments passed in the `func` argument of our `debounce`
method in a single variable.
*/
var context = this, /* 1 */
args = arguments; /* 2 */
/*
Assign an anonymous function to a variable named `later`.
This function will be passed in the first argument of the
`setTimeout` function below.
*/
var later = function() {
/*
When the `later` function is called, remove the numeric ID
that was assigned to it by the `setTimeout` function.
Note, by the time the `later` function is called, the
`setTimeout` function will have returned a numeric ID to
the `timeout` variable. That numeric ID is removed by
assiging `null` to `timeout`.
*/
timeout = null;
/*
If the boolean value passed in the `immediate` argument
of our `debouce` method is falsy, then invoke the
function passed in the `func` argument of our `debouce`
method using JavaScript's *`apply` method.
*The `apply` method allows you to call a function in an
explicit context. The first argument defines what `this`
should be. The second argument is passed as an array
containing all the arguments that should be passed to
`func` when it is called. Previously, we assigned `this`
to the `context` variable, and we assigned all arguments
passed in `func` to the `args` variable.
*/
if ( !immediate ) {
func.apply(context, args);
}
};
/*
If the value passed in the `immediate` argument of our
`debounce` method is truthy and the value assigned to `timeout`
is falsy, then assign `true` to the `callNow` variable.
Otherwise, assign `false` to the `callNow` variable.
*/
var callNow = immediate && !timeout;
/*
As long as the event that our `debounce` method is bound to is
still firing within the `wait` period, remove the numerical ID
(returned to the `timeout` vaiable by `setTimeout`) from
JavaScript's execution queue. This prevents the function passed
in the `setTimeout` function from being invoked.
Remember, the `debounce` method is intended for use on events
that rapidly fire, ie: a window resize or scroll. The *first*
time the event fires, the `timeout` variable has been declared,
but no value has been assigned to it - it is `undefined`.
Therefore, nothing is removed from JavaScript's execution queue
because nothing has been placed in the queue - there is nothing
to clear.
Below, the `timeout` variable is assigned the numerical ID
returned by the `setTimeout` function. So long as *subsequent*
events are fired before the `wait` is met, `timeout` will be
cleared, resulting in the function passed in the `setTimeout`
function being removed from the execution queue. As soon as the
`wait` is met, the function passed in the `setTimeout` function
will execute.
*/
clearTimeout(timeout);
/*
Assign a `setTimout` function to the `timeout` variable we
previously declared. Pass the function assigned to the `later`
variable to the `setTimeout` function, along with the numerical
value assigned to the `wait` argument in our `debounce` method.
If no value is passed to the `wait` argument in our `debounce`
method, pass a value of 200 milliseconds to the `setTimeout`
function.
*/
timeout = setTimeout(later, wait || 200);
/*
Typically, you want the function passed in the `func` argument
of our `debounce` method to execute once *after* the `wait`
period has been met for the event that our `debounce` method is
bound to (the trailing side). However, if you want the function
to execute once *before* the event has finished (on the leading
side), you can pass `true` in the `immediate` argument of our
`debounce` method.
If `true` is passed in the `immediate` argument of our
`debounce` method, the value assigned to the `callNow` variable
declared above will be `true` only after the *first* time the
event that our `debounce` method is bound to has fired.
After the first time the event is fired, the `timeout` variable
will contain a falsey value. Therfore, the result of the
expression that gets assigned to the `callNow` variable is
`true` and the function passed in the `func` argument of our
`debounce` method is exected in the line of code below.
Every subsequent time the event that our `debounce` method is
bound to fires within the `wait` period, the `timeout` variable
holds the numerical ID returned from the `setTimout` function
assigned to it when the previous event was fired, and the
`debounce` method was executed.
This means that for all subsequent events within the `wait`
period, the `timeout` variable holds a truthy value, and the
result of the expression that gets assigned to the `callNow`
variable is `false`. Therefore, the function passed in the
`func` argument of our `debounce` method will not be executed.
Lastly, when the `wait` period is met and the `later` function
that is passed in the `setTimeout` function executes, the
result is that it just assigns `null` to the `timeout`
variable. The `func` argument passed in our `debounce` method
will not be executed because the `if` condition inside the
`later` function fails.
*/
if ( callNow ) {
func.apply(context, args);
}
};
};
回答by PippoApps.com
It holds execution of a function until a timeout is expired. This is to avoid continuous execution of functions when not needed. Beware, since underscore.debounce() relies on complex code. Most of times, a simple "if" statement inside the function is much faster than debounce. You can implement a counter, executing method only each N of iterations, or a timeout, checking that at least a certain amount of milliseconds elapsed.
它保持函数的执行,直到超时到期。这是为了避免在不需要时连续执行功能。当心,因为 underscore.debounce() 依赖于复杂的代码。大多数情况下,函数内的简单“if”语句比 debounce 快得多。您可以实现一个计数器,仅在每 N 次迭代或超时时执行方法,检查是否至少经过了一定的毫秒数。