对象用数字作为key时会内存泄漏
发布于 7 年前 作者 heqs 4857 次浏览 来自 问答
this.watchers={ "creature": { id: id} };//如果这样赋值大小正常,200多字节
this.watchers["creature"][id]=id//如果这样赋值,这个对象竟然达到了惊人的12KB,并且ID越大占用内存越大,id=1占用200多字节,id=1000占用12KB
this.watchers["creature"]["_"+id]=id//这样写也正常

大神们这是为什么啊

10 回复

会不会当成数组了。。。用.id呢

@anotherWill id是动态的具体数字,不能用这种方式写吧

应该是被置换为数组了obj[1234],生成了一个含有1234个元素的数组,对象属性用字符串,你应该用${id}

这个绝壁是处理为数组了。。。

你可以选择用

Object.assign(this.watchers["creature"], {id: id})

或者初始化时就创建一个{}

感觉很奇怪啊,我本地试了下不会转成数组

Object的key,数字默认是会转换成string的。

好像是V8对key为数字的object做的优化,在key小于1024时会转换为array,array有序读取很快,不过会消耗更大的内存,arr[1013]不是一个对象而是一个长度为1013的数组了

好坑。。。

解释1

任何对象(json对象/数组)的属性,v8都会按字符串索引。 因此:

var a = [1,2,3,4];
console.log(a[1], a['1']) // 2, 2

虽然,this.watchers[“creature”][id]=id, id为数字,但事实上内存存储的时候,id作为属性还是会存为字符串。

解释二

任何对象,在v8内部都会按以下结构保存 image.png 具体,请看考这篇文章 http://www.jayconrod.com/posts/52/a-tour-of-v8-object-representation

正如你说的,因为 id 为数字,对象内部存储时,会把数字属性存在数组里。

  • 如果 数组比较紧凑,就按连续数组存,比如 var obj = {1:1, 2:1, 9:1}, 内部就会产生一个长度至少为10的数组,好处是访问速度快,坏处是浪费内存。
  • 如果 数组比较疏松,数字属性,会触发字典模式,其好处是节省内存,坏处是反复hash处理,访问速度慢。

“this.watchers[“creature”]["_"+id]=id//这样写也正常” 的原因也解释了吧;

另问一下:对象内存你是用是方法查看的?

回到顶部