不要在循环javascript中创建函数

时间:2015-01-23 03:29:13

标签: javascript loops javascript-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函数,我获得了与梯形图相比的速度。

任何人都可以告诉我这里的交易是什么以及为什么如果我们在第一个例子中获得更多速度,我是否应该再打扰第二个版本中的两行?

2 个答案:

答案 0 :(得分:2)

我相信你的比较存在缺陷。如果你要反转代码。在比较之后放置匿名函数。它会慢一些。 (http://jsperf.com/best-event-listener-practice/5)。以后的代码总是会变慢,因为以前有过这么多的绑定。

答案 1 :(得分:1)

你不应该担心性能 - 我很难想象你会增加数百万的事件监听器。

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

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

VS

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

names.filter(isJpeg);

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

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

在一天结束时,它并不重要,归结为个人偏好,但有一点很清楚的是,性能问题不应该是推动决策的因素,除非是在非常特殊的情况下。一个好的一般规则是在线编写非常短的一次性函数。使用ES6和箭头功能,更多功能可以非常短&#34;并成为内联的候选人。

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

names.filter(function isJpeg(name) { 

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