简体   繁体   English

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

[英]Does creating functions consume more memory

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

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

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

One of the main reasons people advise the use of prototypes is that .foo is created once in the case of the prototype where as this.foo is created multiple times when using the other approach.人们建议使用原型的主要原因之一是.foo在原型的情况下创建一次,而this.foo在使用另一种方法时创建多次。

However one would expect interpreters can optimize this.然而,人们希望口译员可以优化这一点。 So that there is only one copy of the function foo in case A.这样在情况 A 中只有一个函数foo副本。

Of course you would still have a unique scope context for each object because of closures but that has less overhead then a new function for each object.当然,由于闭包,每个对象仍然有一个唯一的范围上下文,但是与每个对象的新函数相比,它的开销更少。

Do modern JS interpreters optimise Case A so there is only one copy of the function foo ?现代 JS 解释器是否优化了 Case A 所以只有一个函数foo副本?

Yes, creating functions uses more memory.是的,创建函数会占用更多内存。

... and, no, interpreters don't optimize Case A down to a single function. ...而且,不,解释器不会将案例 A 优化为单个功能。

The reason is the JS scope chain requires each instance of a function to capture the variables available to it at the time it's created.原因是JS 作用域链要求函数的每个实例在创建时捕获它可用的变量。 That said, modern interpreters are better about Case A than they used to be, but largely because the performance of closure functions was a known issue a couple years ago.也就是说, 现代解释器在案例 A 方面比以前更好,但这主要是因为闭包函数的性能在几年前是一个已知问题。

Mozilla says to avoid unnecessary closures for this reason, but closures are one of the most powerful and often used tools in a JS developer's toolkit.为此,Mozilla 表示要避免不必要的闭包,但闭包是 JS 开发人员工具包中最强大和最常用的工具之一。

Update: Just ran this test that creates 1M 'instances' of Constructor, using node.js (which is V8, the JS interpreter in Chrome).更新:刚刚运行了这个测试,它使用 node.js(即 V8,Chrome 中的 JS 解释器)创建了 100 万个构造函数“实例”。 With caseA = true I get this memory usage:使用caseA = true我得到这个内存使用情况:

{
    rss: 212291584,       //212 MB
    vsize: 3279040512,    //3279 MB
    heapTotal: 203424416, //203 MB
    heapUsed: 180715856   //180 MB
}

And with caseA = false I get this memory usage:使用caseA = false我得到这个内存使用情况:

{
    rss: 73535488,       //73 MB
    vsize: 3149352960,   //3149 MB
    heapTotal: 74908960, //74 MB
    heapUsed: 56308008   //56 MB
}

So the closure functions are definitely consuming significantly more memory, by almost 3X.所以闭包函数肯定会消耗更多的内存,几乎是 3 倍。 But in the absolute sense, we're only talking about a difference of ~140-150 bytes per instance.但在绝对意义上,我们只是在谈论每个实例约 140-150 字节的差异。 (However that will likely increase depending on the number of in-scope variables you have when the function is created). (但是,这可能会增加,具体取决于创建函数时您拥有的范围内变量的数量)。

I believe, after some brief testing in node, that in both Case A and B there is only one copy of the actual code for the function foo in memory.我相信,在 node 中进行一些简短的测试后,在案例 A 和 B 中,内存中只有一个函数foo的实际代码副本。

Case A - there is a function object created for each execution of the Constructor() storing a reference to the functions code, and its current execution scope.情况 A - 为Constructor()每次执行创建了一个函数对象,存储对函数代码的引用及其当前执行范围。

Case B - there is only one scope, one function object, shared via prototype.情况 B - 只有一个作用域,一个函数对象,通过原型共享。

The javascript interpreters aren't optimizing prototype objects either. javascript 解释器也没有优化原型对象。 Its merely a case of there only being one of them per type (that multiple instances reference).它只是一种情况,每种类型只有一个(多个实例引用)。 Constructors, on the other hand, create new instances and the methods defined within them.另一方面,构造函数创建新实例和其中定义的方法。 So by definition, this really isn't an issue of interpreter 'optimization' but of simply understanding what's taking place.所以根据定义,这真的不是解释器“优化”的问题,而是简单地了解正在发生的事情。

On a side note, if the interpreter were to try and consolidate instance methods you would run into issues if you ever decided to change the value of one in a particular instance (I would prefer that headache not be added to the language) :)附带说明一下,如果解释器要尝试合并实例方法,如果您决定在特定实例中更改 one 的值,则会遇到问题(我希望不要在语言中添加令人头疼的问题):)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 调用带有大量参数的 function 是否会消耗更多的 memory? - Does calling a function with a lot of parameters consume more memory? 在Javascript(V8)中,为什么数组上的forEach比简单的for循环消耗更多的内存? - In Javascript (V8) why does forEach on an array consume much more memory than a simple for loop? 命名事件处理程序是否比 JavaScript 中的匿名事件处理程序消耗更多 memory? - Are named event handlers consume more memory than anonymous ones in JavaScript? JavaScript声明的函数在加载脚本时消耗多少内存? - How much memory does a JavaScript declared function consume on script loading? 对于Javascript中的嵌套对象,{}消耗的内存少于[]吗? - Does {} consume less memory than [] for nested objects in Javascript? 在V8中,为什么预分配的阵列消耗更少的内存? - In V8 why does a preallocated array consume less memory? 在循环中使用JavaScript regexp文字会消耗不必要的内存吗? - Does using JavaScript regexp literals in loops consume unnecessary memory? 在不使用赋值的情况下使用var声明JavaScript中的变量会消耗内存吗? - Does declaring a variable in JavaScript with var without assignment consume memory? 在Typescript中创建(甚至更多的泛型)函数 - Creating (even more generics) functions in Typescript 通过函数创建对象-内存使用 - Creating objects through functions - memory usage
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM