There are two things going on here in regards to the use of apply:
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
timeout = null;
if (!immediate) func.apply(context, args);
}, wait);
if (immediate && !timeout) func.apply(context, args);
};
};
First, the context is being captured outside of the setTimeout callback. So whatever this binding rule is used to determine the initial context (which is dependent on how the depounced function is called later), it is being passed through to the callback function.
Alternately, you could do something like:
setTimeout(function() {
...
func.apply(this, args);
}.bind(this), wait);
The second thing happening is the preservation of the arguments. apply here is used as a way to transfer the arguments (again, importantly captured outside the setTimeout callback) that you would pass to the original function. Because it takes an array (as opposed to call), it makes for an easy transfer.
So if you had something like like:
debouncedFunction(a, b)
The inner func is called appropriately as func(a, b).