一尘不染

使用匿名函数会影响性能吗?

javascript

我一直想知道,在Javascript中使用命名函数和匿名函数之间是否存在性能差异?

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = function() {
        // do something
    };
}

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

第一个是比较整洁的,因为它不会因很少使用的函数而使您的代码混乱,但是多次重声明该函数是否重要呢?


阅读 365

收藏
2020-05-01

共1个答案

一尘不染

这里的性能问题是在循环的每次迭代中创建一个新的函数对象的成本,而不是您使用匿名函数的事实:

for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = function() {
        // do something    
    };
}

即使它们具有相同的代码体并且没有绑定到词法范围(闭包),您仍在创建一千个不同的函数对象。另一方面,下面的方法看起来更快,因为它在整个循环中只是将相同的函数引用分配给数组元素:

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

如果要在进入循环之前创建匿名函数,然后仅在循环内部将对它的引用分配给数组元素,则与命名函数版本相比,您将发现没有任何性能或语义差异:

var handler = function() {
    // do something    
};
for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = handler;
}

简而言之,使用匿名函数而不是命名函数没有明显的性能损失。

顺便说一句,从上方看似乎没有什么区别:

function myEventHandler() { /* ... */ }

和:

var myEventHandler = function() { /* ... */ }

前者是 函数声明,而后者是对匿名函数的变量赋值。尽管它们看起来可能具有相同的效果,但JavaScript确实对它们的处理略有不同。为了理解它们之间的区别,我建议阅读“JavaScript函数声明歧义。

任何方法的实际执行时间在很大程度上将取决于浏览器对编译器和运行时的实现。有关现代浏览器性能的完整比较,请访问JSPerf网站。

2020-05-01