【问题标题】:Is there a performance penalty for binding multiple event handlers to the scroll event?将多个事件处理程序绑定到滚动事件是否会降低性能?
【发布时间】:2014-09-21 01:45:33
【问题描述】:

绑定多个$(window).on('scroll', fn)s 与将所有逻辑组合到一个事件处理程序之间是否存在显着 性能差异? p>

我的代码只使用一个事件处理程序就可以更好地组织,但我希望从这个特定模块中获得最快的性能。在这个用例中,可能有 10~100 个处理程序附加到滚动事件。

【问题讨论】:

  • 我认为您可能在这里得到明确答案的唯一方法是对这两种方法进行基准测试,也可能跨目标浏览器进行基准测试
  • 代码流会是什么样子? 10-100 个处理程序中只有一个最终会根据某些条件触发,或者如果您使用单个处理程序进行操作,您最终会触发所有以编程方式在各个处理程序中触发的东西?
  • 你需要去抖动滚动,因为它每秒可以触发几十或几百次。我会从我的去抖滚动事件中触发一个自定义事件,并让许多订阅者监听那个新的自定义事件。
  • 每个实例都在处理它自己的去抖动。

标签: javascript jquery performance jquery-events


【解决方案1】:

在考虑了 Bergi 的评论后,我修改了 AllitativeAlice 的代码。在 Chrome 中使用原生滚动事件 我没有发现这两种方法的速度有任何显着差异。通过复制粘贴到该网页的 JavaScript 控制台运行下面的代码,你会得到什么结果?...

function log() {
  console.log(Array.prototype.join.call(arguments, ' '))
}

var count100 = 0;
var count1 = 0;

function test100() {
  $(window).off('scroll');
  for (var i = 0; i < 100; i++) {
    $(window).on('scroll', function() {
      count100++;
    });
  }
  var startTime = performance.now();

  for (var x = 0; x < 100; x++) {
    window.scroll(0, 0);

    for (var j = 0; j < 100; j++) {
      window.scroll(0, j + 1);
    }
  }

  var endTime = performance.now();
  log("100 handlers: ", endTime - startTime);
}


function test1() {
  var count = 0;
  $(window).off('scroll');
  var fns = [];
  for (var i = 0; i < 100; i++) {
    fns.push(function() {
      count1++;
    });
  }

  $(window).on('scroll', function() {
    fns.forEach(function(f) {
      f();
    })
  });

  var startTime = performance.now();

  for (var x = 0; x < 100; x++) {
    window.scroll(0, 0);

    for (var j = 0; j < 100; j++) {
      window.scroll(0, j + 1);
    }
  }

  var endTime = performance.now();
  log("1 handler: ", endTime - startTime);
}

var testCount = 0;
var numberOfRuns = 20;

function logCount() {
  console.log("-->count1: ", count1);
  console.log("-->count100: ", count100);
}

function runTestA() {
  test1();
  if (++testCount<numberOfRuns) setTimeout(runTestB, 10);
  else setTimeout(logCount, 10);
}

function runTestB() {
  test100();
  if (++testCount<numberOfRuns) setTimeout(runTestA, 10);
  else setTimeout(logCount, 10);
}

runTestA();

【讨论】:

  • 我尝试运行它,但由于某种原因,处理程序似乎根本没有执行(通过在每次测试结束时记录 count 的值以及结果时间来测试。)我认为这可能是由于 $(window).off('scroll'); 显然是在每次测试中绑定滚动处理程序之后被调用的,但事实并非如此。
  • 感谢@AlliterativeAlice 的反馈,我无法使用内联代码编辑器让它工作,但如果你粘贴到控制台,它现在可以工作了。
猜你喜欢
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多