underscore.js去抖函数中的内部函数上下文

时间:2014-09-02 14:05:14

标签: javascript function underscore.js debouncing

我试图理解underscore.js去抖功能的机制: http://underscorejs.org/#debounce

以下是其原生代码:

_.debounce = function(func, wait, immediate) {
    var timeout, args, context, timestamp, result;

    var later = function() {
      var last = _.now() - timestamp;

      if (last < wait && last > 0) {
        timeout = setTimeout(later, wait - last);
      } else {
        timeout = null;
        if (!immediate) {
          result = func.apply(context, args);
          if (!timeout) context = args = null;
        }
      }
    };

    return function() {
      context = this;
      args = arguments;
      timestamp = _.now();
      var callNow = immediate && !timeout;
      if (!timeout) timeout = setTimeout(later, wait);
      if (callNow) {
        result = func.apply(context, args);
        context = args = null;
      }

      return result;
    };
  };

我遇到的问题是内部可退回函数中使用的上下文变量。我不明白为什么我们应该在这里使用它以及它包含什么上下文。 我尝试使用相同的函数与debounced函数的简单调用,而不应用任何上下文,它也运作良好。 这是我的小提琴这两个功能: http://jsfiddle.net/vlrt/fby9dhe0/11/

那么,这里的背景是必要的吗?需要应用哪些背景?

2 个答案:

答案 0 :(得分:1)

上下文是this,用于调用函数的去抖动版本。如果我们在对象上对方法进行去抖动,那么我们将使用object.debounced_function来调用它,但是我们希望使用与this相同的对象来调用原始函数。

如果debounced函数不是对象方法,或者调用没有this,则上下文将为null或window或其他内容,并且原始函数将被调用为{{{ 1}},但没人会关心。

我假设您理解this方法,它调用具有特定上下文(Function#apply)和参数集的函数。

答案 1 :(得分:0)

您能举一些具体的例子吗? 这是我的代码,但是 1.申请(context,args); 2. func(); 他们使用相同的控制台,但不应这样做吗?

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;
  this.a =222;
  // 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);
        func();
      }
    }, wait);

    // Immediate mode and no wait timer? Execute the function..
    if (callNow) func.apply(context, args);
  }
}

function test() {
    this.a = 100;
    this.b = 200;
}
test.prototype.m1 = function() {
    console.log("m1", this.a);
}
var tt = new test();
debounce(tt.m1, 1000)();