Javascript 创建函数会消耗更多内存吗

Javascript 创建函数会消耗更多内存吗,javascript,v8,spidermonkey,Javascript,V8,Spidermonkey,人们建议使用原型的一个主要原因是,在原型的情况下,.foo创建一次,其中as这个.foo在使用另一种方法时创建多次 然而,有人会期望口译员能够优化这一点。因此,在案例A中,函数foo只有一个副本 当然,由于闭包的存在,每个对象仍然有一个唯一的作用域上下文,但这比每个对象使用一个新函数的开销要小 现代JS解释器是否优化了案例A,因此函数只有一个副本foo?是的,创建函数会占用更多内存 。。。而且,不,口译员不会将案例优化为单个函数 原因是需要函数的每个实例捕获创建时可用的变量。这就是说,它们比以前

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

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

当然,由于闭包的存在,每个对象仍然有一个唯一的作用域上下文,但这比每个对象使用一个新函数的开销要小


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

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

。。。而且,不,口译员不会将案例优化为单个函数

原因是需要函数的每个实例捕获创建时可用的变量。这就是说,它们比以前更接近于案例A,但主要是因为闭包函数的性能在几年前是一个已知的问题

Mozilla之所以这么说是因为这个原因,但闭包是JS开发人员工具包中最强大、最常用的工具之一

更新:刚刚运行,使用node.js(Chrome中的js解释器V8)创建了1M个构造函数“实例”。使用
caseA=true
我可以得到以下内存使用情况:

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

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

Constructor.prototype.foo = function() {
  ...
}
{
    rss: 212291584,       //212 MB
    vsize: 3279040512,    //3279 MB
    heapTotal: 203424416, //203 MB
    heapUsed: 180715856   //180 MB
}
通过
caseA=false
我得到了这个内存使用率:

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

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

Constructor.prototype.foo = function() {
  ...
}
{
    rss: 212291584,       //212 MB
    vsize: 3279040512,    //3279 MB
    heapTotal: 203424416, //203 MB
    heapUsed: 180715856   //180 MB
}

因此,闭包函数无疑消耗了大量内存,几乎是原来的3倍。但从绝对意义上讲,我们只讨论每个实例大约140-150字节的差异。(但是,这可能会随着创建函数时范围内变量的数量而增加)。

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


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

我相信,在node中进行一些简短的测试之后,在A和B两种情况下,内存中只有函数
foo
的实际代码的一个副本

案例A-每次执行
构造函数()
时都会创建一个函数对象,用于存储对函数代码及其当前执行范围的引用


案例B-只有一个作用域,一个函数对象,通过原型共享。

编译器确实优化了函数,但没有优化作用域上下文。尽管如此,每个解释器如何处理重复项似乎并不是真正的问题,解释器需要在多个实例方法之间建立差异,这种差异将消耗更多内存对于案例a,我希望编译器看到构造函数中没有局部变量,因此不需要将其变量对象保留在实例的作用域链上。如果使用了局部变量,它就无法做到这一点,除非它足够聪明,能够在内部函数不引用它们的情况下优化变量对象。无论如何,我会使用原型方法,因为它更整洁、更容易维护(当然是IMO)。我们能有一些参考资料来定义“更好”和“现代口译员”吗您的测试也与我在我的测试中发现的匹配---我还在函数中添加了一些大的代码块,以测试这是否使内存膨胀更快-但它没有。。。函数中的代码不需要额外的内存。哦,我还记录了测试前后的内存使用情况,以测量创建对象之前的差异。这很值得对照chrome canary v32进行检查。看起来有一些改进。你能发布测试代码吗?我确信解释器内部正在进行一些优化,以避免每次解析函数代码,但每次通过构造函数都必须捕获对任何作用域内变量的引用,以便在调用函数时正确解析这些变量。@broofa-将我的代码与你的代码进行比较,基本上是一样的…:)-我刚刚从函数中的其他东西中转储了40行代码来测试它。。。