javascript - 不要在循环 Javascript 中创建函数

标签 javascript loops dom-events event-listener

我知道可能有三百个这样的问题,我明白为什么不问。如果我们循环说一个常规的 for 循环,每次迭代我们都会创建一个匿名函数表达式,它会使用更多内存。相反,我们将函数置于循环之外,从而为其命名

匿名函数迭代示例

var elements = document.getElementsByClassName('elementName');
for(var i=0; i < elements.length; i++ )
{
  elements[i].addEventListener('click',function(e){
    console.log(e);
  });
}

命名函数迭代示例

function handleClickEvents(e) {
   console.log(e);
}

var elements = document.getElementsByClassName('elementName');
for(var i=0; i < elements.length; i++ )
{
  elements[i].addEventListener('click',handleClickEvents);
}

这里的问题是试图向某人证明此逻辑,老实说,我的 jsperfs 完全反驳了我。请自行查看测试结果 here

那么 jsPerf 只是计算错误还是这只是一个完全破灭的神话?我发现通过将匿名函数作为我的 eventListener 函数运行,与阶梯相比,我获得了速度。

任何人都可以告诉我这里的交易是什么以及为什么如果我们在第一个示例中获得更快的速度,我什至还要在第二个版本中多写两行吗?

最佳答案

您不必担心性能——我很难想象您要添加数百万个事件监听器。

第二种选择(指定函数引用)的优越性在于函数一旦定义,就可以在其他地方使用。它需要更少的 });,因此更不容易出现拼写错误。也许更重要的是,它可能更具可读性。让我们以将函数传递给 Array#filter 为例,检查文件名是否为 jpg:

names.filter(function(name) { 
    return /\.jpg$/i.test(name);
});

对比

function isJpeg(name) { return /\.jpg$/i.test(name); }

names.filter(isJpeg);

如果您将方法链接在一起,好处会变得更加明显:

names . filter(isJpeg) . map(makeThumbnail) . forEach(uploadJpg);

归根结底,这并不重要,归根结底是个人喜好,但有一点很清楚,性能问题不应该成为驱动您做出决定的因素,除非在非常特殊的情况下。一个好的通用规则是编写非常短的、一次性的内联函数。使用 ES6 和箭头函数,更多的函数可以“非常短”并成为内联的候选对象。

顺便说一句,即使是内联编写函数,给它起个名字通常也是个好主意:

names.filter(function isJpeg(name) { 

这有两个好处。首先,它是一种文档/注释形式,可以帮助人们阅读您的代码。其次,大多数调试器和堆栈跟踪会更好地报告函数。大多数缩小器会删除名称,因此不会影响生产。

关于javascript - 不要在循环 Javascript 中创建函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28102551/

相关文章:

javascript - 显示星期几

php - 循环一个有间隙数字键的数组

MySQL存储过程用游标查找所有错误日期值

javascript - 无法输入丰富的值 :inplaceInput tag on Chrome version 45. 0.2454.85 m

javascript - 统一事件和 Promise 是 JS/Node

javascript - 完全剪切和粘贴一个元素

javascript - 在 Blade 中将 Laravel 数组值转换为 Javascript 变量

javascript - 处理当前表单上的所有事件后运行的排队函数

c++ - 使循环边界无效

javascript - 如何区分鼠标 "click"和 "drag"