我想知道JavaScript对象占用的大小。

取以下函数:

function Marks(){
  this.maxMarks = 100;
}

function Student(){
  this.firstName = "firstName";
  this.lastName = "lastName";
  this.marks = new Marks();
}

现在我实例化这个学生:

var stud = new Student();

这样我就可以做

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

etc.

现在,stud对象将在内存中占据一定大小。它有一些数据和更多的对象。

我如何找出有多少内存stud对象占用?类似于JavaScript中的sizeof() ?如果我能在一个函数调用中找到它,比如sizeof(stud),那就太棒了。

我已经在网上搜索了几个月了——没有找到它(在几个论坛上被问到——没有回复)。


当前回答

我在原来的答案中重构了代码。我已经删除了递归和假定存在的开销。

function roughSizeOfObject( object ) {

    var objectList = [];
    var stack = [ object ];
    var bytes = 0;

    while ( stack.length ) {
        var value = stack.pop();

        if ( typeof value === 'boolean' ) {
            bytes += 4;
        }
        else if ( typeof value === 'string' ) {
            bytes += value.length * 2;
        }
        else if ( typeof value === 'number' ) {
            bytes += 8;
        }
        else if
        (
            typeof value === 'object'
            && objectList.indexOf( value ) === -1
        )
        {
            objectList.push( value );

            for( var i in value ) {
                stack.push( value[ i ] );
            }
        }
    }
    return bytes;
}

其他回答

如果您主要关心的是Firefox扩展的内存使用情况,我建议您咨询Mozilla开发人员。

Mozilla在其wiki上提供了一系列分析内存泄漏的工具。

非常感谢所有为此编写代码的人!

我只是想补充一点,我一直在寻找完全相同的东西,但在我的情况下,它是为了管理已处理对象的缓存,以避免不得不重新解析和处理来自ajax调用的对象,这些调用可能已被浏览器缓存,也可能未被浏览器缓存。这对于需要大量处理的对象特别有用,通常不是JSON格式的任何东西,但将这些东西缓存在大型项目或长时间运行的应用程序/扩展中成本非常高。

不管怎样,我用它来做一些事情,比如:

var myCache = {
    cache: {},
    order: [],
    size: 0,
    maxSize: 2 * 1024 * 1024, // 2mb

    add: function(key, object) {
        // Otherwise add new object
        var size = this.getObjectSize(object);
        if (size > this.maxSize) return; // Can't store this object

        var total = this.size + size;

        // Check for existing entry, as replacing it will free up space
        if (typeof(this.cache[key]) !== 'undefined') {
            for (var i = 0; i < this.order.length; ++i) {
                var entry = this.order[i];
                if (entry.key === key) {
                    total -= entry.size;
                    this.order.splice(i, 1);
                    break;
                }
            }
        }

        while (total > this.maxSize) {
            var entry = this.order.shift();
            delete this.cache[entry.key];
            total -= entry.size;
        }

        this.cache[key] = object;
        this.order.push({ size: size, key: key });
        this.size = total;
    },

    get: function(key) {
        var value = this.cache[key];
        if (typeof(value) !== 'undefined') { // Return this key for longer
            for (var i = 0; i < this.order.length; ++i) {
                var entry = this.order[i];
                if (entry.key === key) {
                    this.order.splice(i, 1);
                    this.order.push(entry);
                    break;
                }
            }
        }
        return value;
    },

    getObjectSize: function(object) {
        // Code from above estimating functions
    },
};

这是一个简单的例子,可能会有一些错误,但它给出了一个想法,因为你可以使用它来保持静态对象(内容不会改变)与某种程度的智能。这可以大大减少任何昂贵的处理要求,对象必须在第一时间生产。

在@Dan已经很紧凑的解决方案的基础上,这里有一个它的自包含函数版本。对于那些希望变量名尽可能紧凑而不考虑上下文的人来说,变量名被简化为单个字母。

const ns = {}; ns.sizeof = function(v) { let f = ns.sizeof, //this needs to match the name of the function itself, since arguments.callee.name is defunct o = { "undefined": () => 0, "boolean": () => 4, "number": () => 8, "string": i => 2 * i.length, "object": i => !i ? 0 : Object .keys(i) .reduce((t, k) => f(k) + f(i[k]) + t, 0) }; return o[typeof v](v); }; ns.undef; ns.bool = true; ns.num = 1; ns.string = "Hello"; ns.obj = { first_name: 'John', last_name: 'Doe', born: new Date(1980, 1, 1), favorite_foods: ['Pizza', 'Salad', 'Indian', 'Sushi'], can_juggle: true }; console.log(ns.sizeof(ns.undef)); console.log(ns.sizeof(ns.bool)); console.log(ns.sizeof(ns.num)); console.log(ns.sizeof(ns.string)); console.log(ns.sizeof(ns.obj)); console.log(ns.sizeof(ns.obj.favorite_foods));

如果您需要以编程方式检查aprox。对象的大小,你也可以检查这个库http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/,我已经能够用于对象大小。

否则,我建议使用Chrome/Firefox堆分析器。

对不起,我不能评论,所以我只能从明天开始继续工作。 此增强版本不会对对象进行多次计数,因此不会出现无限循环。 另外,我认为一个物体的键也应该粗略地计算。

function roughSizeOfObject( value, level ) {
    if(level == undefined) level = 0;
    var bytes = 0;

    if ( typeof value === 'boolean' ) {
        bytes = 4;
    }
    else if ( typeof value === 'string' ) {
        bytes = value.length * 2;
    }
    else if ( typeof value === 'number' ) {
        bytes = 8;
    }
    else if ( typeof value === 'object' ) {
        if(value['__visited__']) return 0;
        value['__visited__'] = 1;
        for( i in value ) {
            bytes += i.length * 2;
            bytes+= 8; // an assumed existence overhead
            bytes+= roughSizeOfObject( value[i], 1 )
        }
    }

    if(level == 0){
        clear__visited__(value);
    }
    return bytes;
}

function clear__visited__(value){
    if(typeof value == 'object'){
        delete value['__visited__'];
        for(var i in value){
            clear__visited__(value[i]);
        }
    }
}

roughSizeOfObject(a);