【问题标题】:Why does throttle set timeout, context and args to null?为什么throttle 将 timeout、context 和 args 设置为 null?
【发布时间】:2014-04-22 14:24:11
【问题描述】:

所以我只是想了解 underscore.js 中节流阀的代码。

_.throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;
    options || (options = {});
    var later = function() {
        previous = options.leading === false ? 0 : _.now();
        timeout = null;
        result = func.apply(context, args);
        context = args = null;
    };
    return function() {
        var now = _.now();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0) {
            clearTimeout(timeout);
            timeout = null;
            previous = now;
            result = func.apply(context, args);
            context = args = null;
        } else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return result;
    };
};

我想知道为什么上下文、参数和超时设置为空。我最初认为设置它们是为了帮助垃圾收集。为了测试我创建了一个大字符串,将它传递给一个函数并限制该函数。我使用 Chrome 开发工具拍摄了两张快照 - 第一张将三个变量设置为 null 的行已注释掉,另一行未注释掉。

var dummyFunc1 = function(testStr) {
  console.log("HELLO");
};

var dummyFunc2 = function(testStr) {
  console.log("BOOM");
}

var dummyFunc3 = function(testStr) {
  console.log("STOOP");
}

var testStr = '';
for (var i = 0; i < 1000000; i++){
  testStr += i;
}

var largeThrottled1 = _.throttle(dummyFunc1, 1000);
var largeThrottled2 = _.throttle(dummyFunc2, 1000);
var largeThrottled3 = _.throttle(dummyFunc3,1000);

largeThrottled1(testStr);
largeThrottled1(testStr);

不过,好像差别不大。

那么为什么会有这些行呢?

【问题讨论】:

    标签: javascript underscore.js


    【解决方案1】:

    我认为它与防止内存泄漏有关,正如您已经想到的那样。
    假设您创建了大量的节流函数,用大量数据调用它们,然后再也不调用它们。然后_.throttle 创建的函数仍然会在闭包范围内保留对该数据的引用。理论上,返回的函数仍然可以访问它们,因此只要您不处理受限制的函数,GC 就无法清理该数据。因此,将这些变量设置为 null 可确保周围没有不再使用的引用,从而防止内存泄漏。

    【讨论】:

    • _.throttle 的作用域创建的函数被 GC'd 后它们无法访问,尽管如果该作用域或其内部作用域包含 eval 调用并且永远不会发生这种情况如果它的作用域是全局作用域,就会发生。
    • 但是_.throttle创建的函数可能永远不会被GC,因为它们被保留了。也许你有成千上万个知道如何更新自己的对象,更新功能被限制了。仅仅因为你有这些东西,并不意味着你想保留上次调用的上下文、参数等。
    猜你喜欢
    • 2019-09-12
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 2011-09-13
    相关资源
    最近更新 更多