在内存中存储对 HTML 元素的引用与字符串或数字时,内存消耗的差异有多大?
const el = document.getElementById("myEl");
const myCache = new Set()
// store reference to element
myCache.add(el);
// VS store a random string
myCache.add("someStr");
// VS store a random number
myCache.add(0);
这在内存中看起来如何,其中对内存最友好的解决方案是什么。
让我们先看看 chrome heap dump 的内存消耗。
A Set 1509 个字符串,每个字符串 144 个字符 消耗 231776 字节:
一组 1509 个字符串,每个 72 个字符 消耗 111056 字节:
一组 1509 个字符串,每个 36 个字符 消耗 50696 字节:
因此,字符串集合的大小随每个项目长度的大小而变化,但内存大小对于元素和数量是一致的。
现在来回答你的问题。内存效率最高的方法可能因用例而异。
一组元素实际上将存储元素引用。 JS 中对象引用的大小是 8bytes。
一组元素引用可能看起来是一个消耗一致内存的解决方案,因为该集合只保存对元素的引用,并且元素的内存已经分配,因为它是 DOM 的一部分。所以没有什么真正增加。
但是,使用元素引用创建集合的一个问题是,如果我们在从 DOM 中删除元素后不删除元素引用,由于元素引用保留在集合中,它将继续消耗为此分配的内存删除的元素。如果在页面上添加/删除元素非常频繁,并且集合持有所有元素引用,则可能导致内存泄漏。在这种情况下,我们必须从集合中删除已删除的元素引用。
Element.isConnected
是一个布尔属性,如果元素仍然附加到 DOM,则为 true;如果元素已从 DOM 中删除,则为 false。
一组字符串,字符串将作为值存储在集合中,因此如果您已经在其他地方保存值,它将被复制[这就是我的想法,有可能针对浏览器进行特定优化]。集合的大小将取决于您添加的字符串的大小。
现在对于一组数字,数字也将存储为值。 JS 中的一个数字占用 8 个字节。所以在这里你也可以获得一致的尺寸。
Conclusion Based on same size set for different data types
对象引用以及字符串或数字占用多少空间是特定于 JavaScript 引擎的实现。但是如果我们从 V8(Chromium 和 Node.js 中使用的引擎)开始:
对对象的引用,即您在 el 变量中的内容,占用 8 个字节。
参见:https://www.mattzeunert.com/2017/03/29/v8-object-size.html
在这种情况下它是 DOM 元素,也许 V8 和 Blink 之间的绑定增加了一些东西?不确定。
但总的来说:对象引用需要存储的是内存中的地址。
由 7 个字符组成的字符串将占用 20 个字节。
参见:这个公式:12 + 4 * Math.ceil(n/4) 在这里找到v8 需要多少内存来存储一个字符串?
据我所知,数字存储为 64 位浮点数(8 字节)。
所以我从上面的事实猜测是字符串会消耗最多的内存,而数字和对象引用在内存消耗方面相当相等。但这是一个猜测,因为我不知道是否有任何内存压缩算法位于所有这些之上,在这种情况下,可能会压缩几个相同或相似的数字或对同一对象的多个引用。