我只是想知道函数对象的开销是多少。在OOP设计模型中,您可以使用自己的私有函数生成很多对象,但是如果您有10,000多个,我认为这些私有函数对象会产生大量开销。我想知道是否有足够的情况将这些函数移动到实用程序类或外部管理器以保存这些函数对象占用的内存。
答案 0 :(得分:7)
这是Chrome处理功能的方式,其他引擎可能会执行不同的操作。
我们来看看这段代码:
var funcs = [];
for (var i = 0; i < 1000; i++) {
funcs.push(function f() {
return 1;
});
}
for (var i = 0; i < 1000; i++) {
funcs[0]();
}
现在,引擎创建了1000个函数。
单个函数本身几乎不占用任何内存(在这种情况下为36个字节),因为它只保存一个指向所谓的SharedFunctionInfo对象的指针,该对象基本上是对源代码中函数定义的引用* 。这称为lazy parsing。
只有在经常运行它时,JIT才会启动,并创建该函数的编译版本,这需要更多内存。因此,funcs[0]
最终占用256个字节:
*)这不完全正确,它还包含范围信息,函数名称and other metadata,这就是为什么在这种情况下它的大小为592字节。
答案 1 :(得分:3)
首先,将方法放在对象构造函数原型中是很常见的,因此它们将在给定对象的所有实例之间共享:
function MyObject() {
....
}
MyObject.prototype.do_this = function() {
...
}
MyObject.prototype.do_that = function() {
...
}
另请注意,“函数对象”是一个常量的仅代码块或闭包;在这两种情况下,大小与代码无关:
x = [];
for (var i=0; i<1000; i++) {
x.push(function(){ ... });
}
数组中每个元素的大小不依赖于代码大小,因为代码本身将在所有函数对象实例之间共享。 1000个实例中的每一个都需要一些内存,但它与其他对象(如字符串或数组)所需的量大致相同,并且与函数内部存在代码的数量无关。
如果使用Javascript eval
创建函数,情况会有所不同:在这种情况下,我希望每个函数都能占用相当大的代码并且与代码大小成比例,除非在某些情况下也进行了一些超级智能缓存和共享这个级别。
答案 2 :(得分:2)
实际上,函数对象占用了大量空间。对象本身可能不会占用太多空间,如下所示,但功能对象似乎占用了更多。为了测试这个,我使用了Function("return 2;")
来创建一个匿名函数数组。
结果如OP所暗示的那样。事实上这些确实占用了空间。
创建
创建的这些Function()
中有100,000个导致75.4 MB被使用,从0开始。我在一个更受控制的环境中运行此测试。这种转换更加明显,它表明每个函数对象将消耗754个字节。这些都是空的。较大的功能对象可能超过1kb,这将非常快速地变得显着。在客户端上调整75MB是非常重要的,并且导致了近4秒的UI锁定。
这是我用来创建函数对象的脚本:
fs = [];
for(var i = 0; i < 100000; i++ ){
fs.push(Function("return 2;"));
}
调用这些函数也会影响内存级别。调用这些函数会增加34MB的内存使用量。
调用
这就是我以前称之为:
for( var i = 0; i < fs.length; i++ ){
for( var a = 0; a < 1000; a++ ){
fs[i]();
}
}
在编辑模式下使用jsfiddle很难得到准确的结果,我建议将其嵌入。
<强> Embedded jsFiddle Demo
强>
这些陈述不正确,我留下它们以允许评论保留上下文。
函数对象根本不占用太多空间。可用的操作系统和内存将最终决定如何管理这些内存。这不会真正影响您应该担心的任何规模。
在我的电脑上加载时,一个相对空白的jsfiddle消耗了5.4MB的内存。创建100,000个函数对象后,它跳转到7.5MB。这似乎是每个函数对象的一个微不足道的内存量(每个函数对象的含义为21个字节:7.5M-5.4M / 100k)。
击>
<击> <强> jsFiddle Demo
强> 撞击>