在JavaScript中使用匿名函数有什么缺点吗?比如内存使用?

Pau*_*ite 31 javascript memory

在过去的某个时刻,我读到了一些让我觉得JavaScript中的匿名函数可以消耗大量内存的想法(因为它们带有整个当前范围),而命名(静态?)函数不是'有这个问题.

我不记得我在哪里读到这个,所以我不能回去重新阅读它并为自己弄清楚这一点.

我有两个问题:

  1. 是否存在匿名函数可以使用足够内存以使其值得关注的情况?(如果是的话,你有一个例子吗?)
  2. 匿名函数是否有任何其他缺点(与命名/静态函数相反)?

use*_*716 8

所有JavaScript函数的行为方式都相同,因为它们继承了整个作用域链中的变量环境,直到并包括它们自身.对于匿名和命名函数同样如此.

即使函数被传递到完全不同的范围,这个对外部环境的引用链仍然保留在每个函数中.

传统上,这意味着只要内部闭包继续存在,任何给定链中的所有变量都会保留一个引用.虽然在编译代码的现代浏览器中,可能会分析哪些变量实际被引用,并且只保留那些变量,允许不再引用的其他变量被垃圾收集.

但是,还有其他情况下匿名函数是浪费的.

这是一个常见的代码:

for( var i = 0; i < 100; i++ ) {
    (function( j ) {
        setTimeout( function() { console.log( j ); }, 1000 );
    })( i );
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,匿名函数比命名函数更浪费,因为您在循环期间重新创建相同的函数100次,而您可以重用已命名的函数.

function setConsole( j ) {
    setTimeout( function() { console.log( j ); }, 1000 );
}

for( var i = 0; i < 100; i++ ) {
    setConsole( i );
}
Run Code Online (Sandbox Code Playgroud)

这具有完全相同的闭包开销,但更有效,因为您只构造了一个函数来创建每个新的变量环境.

http://jsperf.com/immediate-vs-named (感谢@Felix Kling为jsPerf.)

因此,特别是对于闭包,只要您通过一些永久性引用来保持闭包,就会有开销.我会说如果可能的话,尽量避免这种情况是好的,但不要过于强迫它.有时,添加到范围链中的新变量环境只是最佳解决方案.


编辑: 这是谷歌的一篇文章.具体来说,请参阅避免闭包陷阱.有关扩展范围链的性能影响的信息,以及匿名函数比命名函数"更慢"的声明.