1

假设我从 ajax 调用中得到的 ajax 响应为 5mb。

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?

4

1 回答 1

2

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

所有对象(无论是函数、对象字面量、数组、原型……)都驻留在内存中的某个位置。内存中的这些空间可以被变量引用,也可以不被引用。但他们保持原样。您可以拥有任意数量的变量来分配此对象的地址,但您不能复制对象本身,也不能直接复制。
检查这个答案,其中包含许多图表和有关 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对象,不需要额外的内存......保存存储变量所需的微小内存位。在这个例子中,实际值是
什么,或者在这个例子中是什么。或者在 C 语言中,它们实际上表现为取消引用的指针。ab0XB16B00B6


在某些情况下,人们确实想要复制对象。由于 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'ed。它还将注册第二个对象,该对象被变量引用ajaxdata3,因此该对象也将保留在内存中。
的返回值JSON.stringify也找到了,只是这一次,GC 发现这个字符串常量没有在任何地方被引用,所以它标记了内存的那个部分。下次 GC 启动时,它将检查所有标记的内存位并释放它们(释放它们以供使用)。

于 2013-10-02T06:41:30.553 回答