[英]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.