Javascript中的内存分配用于重复对象

时间:2013-10-02 06:32:22

标签: javascript performance memory

我们假设ajax响应是5mb,我从ajax调用得到。

function(ajaxresponse){

    var ajaxdata = ajaxresponse;

    then

    var ajaxdata2 = ajaxresponse; //as per the reply below this is a reference and hence new memory isn't allocated

    var ajaxdata3 = JSON.parse(JSON.stringify(ajaxresponse));

}

是否会使用15mb,10mb或5mb?

1 个答案:

答案 0 :(得分:1)

这很简单。 JavaScript总是按值传递/分配,但对象的值从不真正分配给变量。在JS中考虑对象和内存管理的方法是这样的:

所有对象(无论是函数,对象文字,数组,原型......)都驻留在内存中。内存中的这些空格可以由变量引用,也可以不引用。但他们保持 put 原样。您可以为任何数量的分配此对象的地址的变量,但不能直接复制对象本身,而不是直接复制。
查看this answer,其中包含许多图表以及有关JS如何工作的更多详细信息,包括指向更多信息的链接......

试试吧:

var a = {foo: 'bar'},
b;
b = a;
console.log(b.foo);//bar
b.foo += ' appended through b reference';
console.log(a.foo);//bar appended through b reference

ab引用相同的对象,不需要额外的内存...保存存储b变量所需的内存位数。
此示例中实际值为ab的内容类似于0XB16B00B6。或者在C语言中,它们实际上表现为一个解除引用的指针。


在某些情况下,人们想要复制对象。由于JS的设计,现在很难完成。如果对象只包含数据,那么最简单的方法是:

var copiedObj = JSON.parse(JSON.stringify(someObject));

但是,如果你正在处理一个也有自己方法的对象,那么你将面临一个全新的麻烦世界,你将不得不做这样的事情:

//after doing:var copiedObj = JSON.parse(JSON.stringify(someObject));
function copyFunctions(srcObj, targetObj)
{
    var prop;
    for (prop in srcObj)
    {
        if (srcObj[prop] instanceof Object)
        {
            if (srcObj[prop] instanceof Function)
            {
                targetObj[prop] = srcObj[prop];//this is a REFERENCE, still
                //OR, to ensure correct this binding!
                targetObj[prop] = (function(rebind, actualFunc)
                {
                    return function()
                    {
                        actualFunc.bind(this);
                        var returnVal = actualFunc.apply(this, [].slice.call(arguments));
                        actualFunc.bind(rebind);
                    };
                }(srcObj, srcObj[prop]));
            }
            else
            {
                if (srcObj.hasOwnProperty(prop))
                {//avoid copying prototypal methods
                    targetObj[prop] = copyFunctions(srcObj[prop], targetObj[prop] || {});
                }
            }
        }
    }
    return targetObj;
}

请注意,此代码仅仅是我的头脑,并没有以任何方式进行测试。它没有检查递归,所以使用它是不安全的...但是我希望你能得到它的主旨。

现在,您的问题中的代码如何改变内存使用情况?简单:JSON.stringify返回一个字符串常量。此字符串不再与原始对象绑定,因此JS将分配新内存以容纳此字符串的内存。然后,此字符串将传递给JSON.parse。同样,将创建新对象,为此对象分配内存(不引用原始对象)是必需的。
在分配给ajaxdata3之后,GC(GarbageCollector)启动。它将找到2个对单个对象的引用,因此该对象不能被GC控制。它还会注册第二个对象,该对象由变量ajaxdata3引用,因此该对象也将保留在内存中。
还发现了JSON.stringify的返回值,只是这次,GC看到这个字符串常量没有被引用到任何地方,因此它标记了内存的那一部分。 GC下次启动时,它会检查所有标记的位内存并取消分配它们(释放它们以供使用)。