【问题标题】:are JavaScript closures memory efficient?JavaScript 闭包内存效率高吗?
【发布时间】:2012-09-22 13:57:03
【问题描述】:

我想更好地了解 JavaScript 闭包对内存的影响:

function fee(arg){

  function figh(){
    //some code
     fum(passOnSomeARG)
  }     

  function fo(y){
    //some calculations with y
  }

  function fum(x){
    //some code
     fo(x)
  }

  figh()
}

在上面的例子中,每次调用“fee()”时,内部函数是否会重新读入内存?如果是这样,这有效吗?如果没有,那么发生了什么?

旁注:fee() 可能会被连续调用很多次(循环或鼠标事件 onmousemove)

【问题讨论】:

  • 如果您询问是否每次调用fee 时都会创建这些内部函数,那么是的,尽管我猜想实现有优化来帮助解决这个问题。而且由于您的内部函数不会存储在fee 调用的生命周期之外,因此它们将被垃圾收集。仍然@Kolink 的回答显示了一个不错的选择。
  • 这里有内部函数,但没有形成闭包,因为没有对任何内部函数的外部引用。在下面的 Kolink 代码中,外部(自执行)函数形成了一个闭包,因为语句 window.fee = function(...){...} 创建了对内部(匿名)函数的外部引用。这里要记住的黄金法则是,只有当内部函数存在持久的外部引用时,才会形成闭包。内部函数本身不会导致闭包的形成。
  • @Beetroot-Beetroot 所以这意味着通过外部引用它可以防止内部函数被垃圾收集,从而防止它们被重新创建?
  • 不完全。如果再次调用外部函数,则将创建内部函数的新实例——有时这是需要的。当存在对至少一个内部函数的外部引用时,就会形成一个闭包,并通过其外部引用调用一个内部函数,使其能够访问在形成闭包时存在的其他内部成员(在本例中为函数)。闭包的本质是保留整个外部环境,但只有存在外部引用的内部函数才能访问它。

标签: javascript memory memory-leaks closures


【解决方案1】:

我想是的,是的。这样做会更有效率:

(function() {
    var figh = function() {
        // some code
        fum(passOnSomeARG);
    };
    var fo = function(y) {
        // some calculations with y
    };
    var fum = function(x) {
        // some code
        fo(x);
    };
    window.fee = function(arg) {
        figh();
    };
})();

【讨论】:

  • +1,但您的无效函数/变量混合语法除外。 ;)
  • @user1689607 : 到底什么是无效的?
  • @c-smile:见revision history。此后已更正。
  • 闭包在某些特定情况下很有帮助,例如function currying。但是,它可能具有负面的性能特征,尤其是在多次执行时(例如在循环中)。不需要就不要使用。
  • 可能值得注意的是,在循环中形成闭包非常有用,甚至是必要的,以使循环相关的值可以在之后访问(内部函数)循环已完成。在执行正确构造的代码时,每个闭包都将包含成员,这些成员反映了循环相关变量在形成时的迭代时的值。这样做的代价是消耗工作内存 (RAM),而不是性能本身。如果处理得当,这个成本不一定很高。
【解决方案2】:

考虑这段代码:

function foo(){
  function local(){ ... local code ... }     
  local();
}

在底层,JS VM 将 foo() 的主体翻译成这个序列(伪代码):

var local = new Function({bytecode: local code});
local();

所以每次调用 foo 时都会分配一个新的函数实例。通常函数实例是相对较小的对象,无论它的主体有多大。但仍然 - 分配发生,堆管理器将忙于收集每次 foo() 调用后留下的垃圾。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 2015-11-08
    • 2012-02-01
    • 2014-10-10
    • 2013-03-27
    • 2019-07-26
    • 2021-05-10
    • 1970-01-01
    相关资源
    最近更新 更多