创建函数是否会消耗更多内存

时间:2011-09-16 23:16:31

标签: javascript v8 spidermonkey

// Case A
function Constructor() {
  this.foo = function() {
    ...
  };
  ...
}

// vs 
// Case B
function Constructor() {
  ...
};

Constructor.prototype.foo = function() {
  ...
}

人们建议使用原型的一个主要原因是.foo在原型的情况下创建一次,其中当使用另一种方法时多次创建this.foo

然而,人们会期望口译员可以优化这一点。因此,在案例A中只有一个函数foo的副本。

当然,由于闭包,每个对象仍然有一个唯一的作用域上下文,但是每个对象的新函数开销较少。

现代JS解释器是否优化了案例A,因此只有一个函数foo的副本?

3 个答案:

答案 0 :(得分:8)

是的,创建函数会占用更多内存。

......而且,不,解释员不会将案例A优化为单一函数。

原因是the JS scope chain要求函数的每个实例捕获创建它时可用的变量。也就是说,modern interpreters关于案例A的better比以前更avoid unnecessary closures,但很大程度上是因为封闭函数的表现是几年前的一个已知问题。

由于这个原因,Mozilla对this test说,但是闭包是JS开发人员工具包中最强大和最常用的工具之一。

更新:使用node.js(即V8,Chrome中的JS解释器)运行{{3}},创建构建器的1M'实例'。使用caseA = true我得到了这个内存使用情况:

{ rss: 212291584,
vsize: 3279040512,
heapTotal: 203424416,
heapUsed: 180715856 }

使用caseA = false我得到了这个内存使用情况:

{ rss: 73535488,
vsize: 3149352960,
heapTotal: 74908960,
heapUsed: 56308008 }

因此闭包函数肯定会消耗更多的内存,几乎是3倍。但从绝对意义上讲,我们只讨论每个实例约140-150字节的差异。 (但是,根据创建函数时的范围内变量的数量,这可能会增加。)

答案 1 :(得分:2)

我相信,在节点中进行了一些简短的测试之后,在案例A和B中,内存中只有一个函数foo的实际代码副本。

案例A - 为每次执行存储对函数代码及其当前执行范围的引用的Constructor()创建了一个函数对象。

案例B - 只有一个范围,一个功能对象,通过原型共享。

答案 2 :(得分:0)

javascript解释器也没有优化原型对象。它只是每种类型中只有一个(多个实例引用)的情况。另一方面,构造函数创建新实例及其中定义的方法。因此,根据定义,这实际上不是解释器“优化”的问题,而是简单地理解正在发生的事情。

另一方面,如果解释器尝试合并实例方法,如果您决定在特定实例中更改一个值,则会遇到问题(我希望不会将头痛添加到语言中) :)